Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Kod doskonały vs rzeczywistość
Forum PHP.pl > Inne > Hydepark
Stron: 1, 2, 3, 4
com
Pyton_000 Wtedy już to nie jest klasa abstrakcyjna, co z tego że dopiszesz sobie słówko abstract i kod zadziała jak to jest niezgodne ze sztuka. Wiem ze tak się czasem robi ale to nagięcie zasady jej istnienia.

http://php.pl/Wortal/Artykuly/PHP/Podstawy...ne-i-interfejsy

Opisany prze Ciebie przypadek owszem jest ale:
Cytat
Klasa abstrakcyjna w Javie nie musi posiadać metod czysto wirtualnych aby być abstrakcyjną, jednak takie użycie klasy abstrakcyjnej określa klasę jako nieinstancjowalną i jest rzadziej spotykane.
Pyton_000
Jest klasa abstrakcyjna bo nadal nie możesz zrobić z niej instancji. Owszem debilne jest to rozwiązanie że nie musi mieć metod ale jest. Jest i działa. Ba nawet coś takiego zadziała:

  1. abstract class Test {
  2.  
  3. static public function goon() {
  4. echo 'ok';
  5. }
  6. }
  7. Test::goon();
com
owszem zgadzam się z Tobą, ale lepiej tego unikać biggrin.gif
Pyton_000
Uważaj nie zgadzaj się tak publicznie bo wykorzystają to przeciwko Tobie biggrin.gif
daro0
No dobra a weźmy takie coś:

  1. class UploaderImage extends Uploader
  2. {
  3. public function __construct($files, $path)
  4. {
  5. parent::construct($files, $path);
  6. // możliwe dodatkowe operacje
  7. }
  8.  
  9. public function execute()
  10. {
  11. // robi upload tego co jest w $_FILES, tutaj wyżej $files
  12. // do wynikowego pliku określonego przez $path jako obrazek
  13. }
  14. }


  1. class UploaderVideo extends Uploader
  2. {
  3. public function __construct($files, $path)
  4. {
  5. parent::construct($files, $path);
  6. }
  7.  
  8. public function execute()
  9. {
  10. // robi upload tego co jest w $_FILES, tutaj wyżej $files
  11. // do wynikowego pliku określonego przez $path jako wideo
  12. }
  13. }


a)

  1. abstract class Uploader
  2. {
  3. protected $files;
  4. protected $path;
  5.  
  6. public static function factory($name, $files, $path)
  7. {
  8. $class = 'Uploader' . ucfirst($name);
  9. return new $class($files, $path);
  10. }
  11.  
  12. public function __construct($files, $path)
  13. {
  14. $this->files = $files;
  15. $this->path = $path;
  16. }
  17.  
  18. abstract public function execute();
  19. }


vs.

cool.gif

  1. class Uploader
  2. {
  3. protected $files;
  4. protected $path;
  5.  
  6. public static function factory($name, $files, $path)
  7. {
  8. $class = 'Uploader' . ucfirst($name);
  9. return new $class($files, $path);
  10. }
  11.  
  12. public function __construct($files, $path)
  13. {
  14. $this->files = $files;
  15. $this->path = $path;
  16. }
  17.  
  18. }


no i w końcu

  1. define('DOCROOT', realpath(dirname(__FILE__) . '/..').DIRECTORY_SEPARATOR);
  2.  
  3. // upload zdjęć
  4. $files = $_FILES['image'];
  5. $path = DOCROOT . 'uploads/images/test.png';
  6.  
  7. $result = Uploader::factory('Image', $files, $path)
  8. ->execute();
  9.  
  10.  
  11. // upload wideo
  12. $files = $_FILES['video'];
  13. $path = DOCROOT . 'uploads/videos/test.mp4';
  14.  
  15. $result = Uploader::factory('Video', $files, $path)
  16. ->execute();


który z przypadków a) albo cool.gif jest właściwy (zgodny ze sztuką)? Tutaj zakładam że każdy z uploaderów ma tak samo nazywającą się metodę execute.
Omenomn
Cytat
Tam masz interfejs wiec zapisujesz do czegokolwiek co implementuje ten interfejs. Przecież nie zrobię Ci gotowca, ja tylko wskazałem drogę która masz iść, Zmiana kodowania,nazwy itd to będą kolejne dekoratory, które sobie dopiszesz w miarę potrzeb.


Zdecyduj się czy zmiana nazwy i kodowania mają być wstrzykiwane, czy dodawane jako dekoratory, bo wcześniej pisałeś, żeby je wstrzykiwać i ciekawe jak zdecydujesz w klasie Upload, którą metodę użyjesz ze wstrzykniętego obiektu, skoro masz tam 5 metod, co użyjesz wszystkich, czy jednej, a jak będziesz chciał użyć innej, to będziesz edytował klasę Upload? Jaki to ma sens?

Cytat
Upload to klasa bazowa, a SessionStorage wgl nie ma znaczenia dla dekoratora. Bo to jest zależność wstrzykiwana do Upload, dlatego możesz wstawić dowolny storage jaki sobie wymarzysz, warunek jest tylko taki musi implementować zdefiniowany interfejs.


Ma znaczenie, bo musisz za każdym razem wrzucić do UploadImage coś co implementuje interfejs z kontruktora, a nie zawsze jest taka potrzeba.
Cytat
Owszem klasa abstrakcyjna może posiadać definicje jakiś wspólnych metod ale musi posiadać co najmniej jedną metodę abstrakcyjną, żeby można było ja nazwać klasa abstrakcyjna, inaczej to jest zwykła klasa.
To są podstawy programowania obiektowego.


Klasa abstrakcyjna ma to do siebie, że oprócz metod abstrakcyjnych, które się w niej dodaje, nie daje możliwości stworzenia z niej bezpośrednio obiektu.
Dopiero z klasy dziedziczącej po klasie abstrakcyjnej, można stworzyć obiekt. Dlatego właśnie klasy abstrakcyjne w moim rozwiązaniu nie posiadają konstruktorów, a gotowe metody, które funkcjonują dopiero po odpowiednim zdefiniowaniu konstruktorów klas dziedziczących. Więc nie chodzi o to:
Cytat
Pyton_000 Wtedy już to nie jest klasa abstrakcyjna, co z tego że dopiszesz sobie słówko abstract i kod zadziała jak to jest niezgodne ze sztuka. Wiem ze tak się czasem robi ale to nagięcie zasady jej istnienia.

żeby dopisać słówko abstract, tylko, żeby nie można było stworzyć z niej obiektu, bo bez konstruktora jest bezużyteczna. Mam nadzieję, że wyjaśniłem.

Cytat
Jest klasa abstrakcyjna bo nadal nie możesz zrobić z niej instancji. Owszem debilne jest to rozwiązanie że nie musi mieć metod ale jest

Zwykła klasa też nie musi mieć metod i co to też jest debilne?

Na koniec chcę dodać, że ten kod jest łatwiejszy do zrozumienia, ale trudniejszy do rozbudowy, dodasz parę rzeczy i zrobi się bagno.
daro0
No rozpacz.

Omenomn

1. Czemu ciągle upierasz się przy swoich racjach i nie dasz sobie wytłumaczyć jak to dobrze (i praktycznie) jako to wydaje mi się com tutaj przedstawił rozwiązanie problemu?

2. Jak długo i przy jakich projektach siedzisz i czy jest to praca zespołowa czy też samodzielna?

3. Ja pracuję samodzielnie i te sprawy związane z elastycznością i rozszerzalnością rozumiem inaczej, ze względu na specyficzną architekturę frameworka i np. ten CFS. Akurat jestem w trakcie tworzenia pewnego serwisu (i to nie małego) i pomimo tego że kod (gdybym Ci pokazał choć fragmenty) to w Twoim mniemaniu byłby syfem, to ja w tym syfie bardzo dobrze się odnajduję i nie mam żadnych problemów z rozszerzaniem czy refaktoryzacją. smile.gif Co nie znaczy że Tobie albo komu innemu by się pracowało dobrze.

4. Do tego samego problemu są różne podejścia. Przejrzyj sobie jak ten Upload można robić przy użyciu wszystkich znanych frameworków PHP, w Wordpressie czy innych rozwiązaniach. Co FW to specyficzne podejście które nie każdemu pasuje (co też widać często po tym hejcie po Laravelu smile.gif

5. Ciekawe jak wygląda praca w zespole gdzie każdy upiera się przy swoich racjach i ile może trwać realizacja projektu, który przy zgraniu można by zrealizować np. w 3 miesiące? O ile w ogóle się powiedzie. I nie chodzi mi tu tylko o backend ale np. ktoś jest frontendowcem a ty robisz w backendzie ale są pewne niezgodności bo upieracie się przy swoich rozwiązaniach smile.gif
com
Cytat
Zdecyduj się czy zmiana nazwy i kodowania mają być wstrzykiwane, czy dodawane jako dekoratory, bo wcześniej pisałeś, żeby je wstrzykiwać i ciekawe jak zdecydujesz w klasie Upload, którą metodę użyjesz ze wstrzykniętego obiektu, skoro masz tam 5 metod, co użyjesz wszystkich, czy jednej, a jak będziesz chciał użyć innej, to będziesz edytował klasę Upload? Jaki to ma sens?


Niczego nie miałbym edytować bo jako parametr ma interfejs a nie implementacje, wiec ta klasa ma dowolna definicje, zgodna jedynie z interfejsem po którym dziedziczy, ale dałem Ci potem przykład, ze równie dobrze te zależności mogą być dekoratorami bo zmieniają oryginalny obiekt.

Cytat
Ma znaczenie, bo musisz za każdym razem wrzucić do UploadImage coś co implementuje interfejs z kontruktora, a nie zawsze jest taka potrzeba.


Daj mi przypadek kiedy upload nie potrzebuje zapisać pliku, nie ma takiego.

Cytat
Klasa abstrakcyjna ma to do siebie, że oprócz metod abstrakcyjnych, które się w niej dodaje, nie daje możliwości stworzenia z niej bezpośrednio obiektu.
Dopiero z klasy dziedziczącej po klasie abstrakcyjnej, można stworzyć obiekt. Dlatego właśnie klasy abstrakcyjne w moim rozwiązaniu nie posiadają konstruktorów, a gotowe metody, które funkcjonują dopiero po odpowiednim zdefiniowaniu konstruktorów klas dziedziczących. Więc nie chodzi o to:


A kto mi zabroni zrobić konstruktor klasy abstrakcyjnej :
http://ideone.com/VcUReV

Cytat
żeby dopisać słówko abstract, tylko, żeby nie można było stworzyć z niej obiektu, bo bez konstruktora jest bezużyteczna. Mam nadzieję, że wyjaśniłem.


Wiem czemu to zastosowałeś, ale nie jest to dobre podejście. Każda klasa ma konstruktor nie ważne jakie słówko sobie przed nią postawisz. Bo jest coś takiego jak konstruktor domyślny, który nie musi być zdefiniowany jawnie i tu kłania się brak podstaw php wink.gif Dlatego tez tworząc singleton musisz
Cytat
The constructor __construct() is declared as protected to prevent creating a new instance outside of the class via the new operator.


Cytat
Na koniec chcę dodać, że ten kod jest łatwiejszy do zrozumienia, ale trudniejszy do rozbudowy, dodasz parę rzeczy i zrobi się bagno, po za tym jeżeli przekazujesz pomiędzy dekoratorami plik bezpośrednio z requesta, to nie możesz zmienić mu nazwy, ani przeedytować go w żaden sposób, więc nadal jest to uproszczone rozwiązanie czysto teoretyczne.


Poproszę choć jeden przykład, w którym miejscu smile.gif

daro0 zły przykład bo oba są poprawne, bo klasa abstrakcyjna daje nam tylko informacje o tym, że potomek potrzebuje jeszcze metody execute i ma to sens, bo unikniemy pomyłek, ale nie jest to wymagane, ale masz rację lepiej jak obiekt o to dba. Tylko, ze jak ktoś napisze to tak jak w przypadku b, to pamiętając o tym, ze ta klasa ma mieć te metodę tez zadziała, tylko poco ma to pamiętać.

Cytat
Zwykła klasa też nie musi mieć metod i co to też jest debilne?


Nie, przykład wprost z jednego z moich projektów, nigdzie w definicji klasy nie masz powiedziane, ze ona ma mieć jakieś metody. Inaczej jest z klasa abstrakcyjna, która ma mieć co najmniej jedną metodę czysto wirtualna/abstrakcyjną.

  1. class Services
  2. {
  3. const KERNEL_COMMAND_EXTENSION_REGISTRY = 'proton.common.command.extension_registry';
  4. const KERNEL_COMMAND_HANDLER_MAP = 'proton.common.command.handler_map';
  5. const KERNEL_SERVICE_LOCATOR = 'proton.common.service.locator';
  6. const KERNEL_TRANSACTION_FACTORY = 'proton.common.transaction.factory';
  7. }
Omenomn
Cytat
Daj mi przypadek kiedy upload nie potrzebuje zapisać pliku, nie ma takiego.

Mówię o wrzucaniu do Upload obiektu klasy SessionStorage. Może nie być potrzeby zapisu do sesji i co wtedy?
Po za tym metoda save() z Upload wygląda tak:
  1. public function save(File $file)
  2. {
  3. $fileName = $file->getName();
  4. if($this->storage->has($fileName))
  5. {
  6. $this->storage->remove($fileName);
  7. }
  8. $this->storage->set($fileName, [
  9. 'file' => $file
  10. ]);
  11. }

Co z resztą metod klasy SessionStorage?

Cytat
A kto mi zabroni zrobić konstruktor klasy abstrakcyjne

Nikt, ale co to ma do rzeczy? Ty stwierdziłeś, że równie dobrze to mogła by być zwykła klasa, a nie mogła by być, bo była by bezużyteczna.

Cytat
Wiem czemu to zastosowałeś, ale nie jest to dobre podejście. Każda klasa ma konstruktor nie ważne jakie słówko sobie przed nią postawisz. Bo jest coś takiego jak konstruktor domyślny, który nie musi być zdefiniowany jawnie i tu kłania się brak podstaw php.


Chyba dalej nie rozumiesz dlaczego użyłem klasy abstrakcyjnej, a nie zwykłej. Co z tego, że konstruktor jest domyślnie definiowany, skoro jest pusty?
Zobacz sobie co dodaję w klasach dziedziczących po ClientMakerAbstract w folderze makerClients to może w końcu pojmiesz.

Nie chce mi się marnować energii i nerwów na tą dyskusje już.
com
Cytat
Mówię o wrzucaniu do Upload obiektu klasy SessionStorage. Może nie być potrzeby zapisu do sesji i co wtedy?


No to do innego storage wtedy go zapiszesz, SessionStorage to tylko przykład. nigdzie nie powiedziałem ze wgl kiedykolwiek użyjesz go w tym miejscu. W Twoim systemie w miejsce SessionStorage wstawisz sobie FileStorage i wtedy zapiszesz te obrazki do pliku, a nie do sesji je wrzucisz.

Cytat
Co z resztą metod klasy SessionStorage?


Ale co Cie one wgl interesują, są żebyś mógł wykonać dowolne operacje na tym obiekcie. A nie tylko to co akurat w tym miejscu potrzebujesz, w innym może się okazać, że potrzebujesz inne.
Zajrzyj sobie do implementacji dowolnego obiektu typu Storage to będziesz wiedział czemu one tam są.

Cytat
Chyba dalej nie rozumiesz dlaczego użyłem klasy abstrakcyjnej, a nie zwykłej. Co z tego, że konstruktor jest domyślnie definiowany, skoro jest pusty?
Zobacz sobie co dodaję w klasach dziedziczących po ClientMakerAbstract w folderze makerClients to może w końcu pojmiesz.


Rozumiem, po to żeby w 8 miejscach mieć dostęp do tych samych metod i właściwości. Ale wystarczyło by ze byś miał w jednym a te klasę wstrzyknął jako zależność.

Cytat
Nikt, ale co to ma do rzeczy? Ty stwierdziłeś, że równie dobrze to mogła by być zwykła klasa, a nie mogła by być, bo była by bezużyteczna.


Nie była by bo ona się u Ciebie nie zmienia, nawet jak tworzysz jej dziecko. Wiec równie dobrze mogła by istnieć bez niego i tez by to działało tak samo jak działa teraz.

Cały twój kod w makerClients to kulawe Proxy, kolejny wzorzec który miał nim być ale nie jest bo nie wyszedł wink.gif
https://github.com/domnikl/DesignPatternsPH...tructural/Proxy
Omenomn
com, zastanów się człowieku co Ty w ogóle mówisz, bo tą Twoją przemądrzałą gadką o klasach abstrakcyjnych negujesz praktyki stosowane we frameworkach klasy Laravela.
Może napisz swój framework na wyższym poziomie niż Symfony i Laravel, a później neguj stosowane w nim praktyki.
Klasa abstrakcyjna w Laravel odpowiedzialna za requesty:
  1. <?php
  2.  
  3. namespace App\Http\Requests;
  4.  
  5. use Illuminate\Foundation\Http\FormRequest;
  6.  
  7. abstract class Request extends FormRequest
  8. {
  9. //
  10. }
  11.  


Skoro takie kwestie negujesz, to jak mógłbym Cię słuchać w innych?
viking
A kto powiedział że Laravel jest dobrze napisany? Jak wygląda HTTP messaging definiują PSR-7 i draft PSR-17. I patrzysz chyba na jakiś stary kod bo obecnie class FormRequest extends Request implements ValidatesWhenResolved
com
Omenomn Coś długo trwało zanim coś wymyśliłeś, ale pierwsze pytanie skąd wgl ten kod masz, bo ja tam nigdzie w źródle laravel nie widzę takiej klasy. A poza tym coś Ty niby udowodnił nie pokazując kodu tej klasy abstrakcyjnej.

Cytat
negujesz praktyki stosowane we frameworkach klasy Laravela


Akurat Laravel to ma parę błędów w architekturze. Co sprawiło, że w Polsce bardziej ceni się Symfony. Na szczęście obecnie można już nie używać Fasad, i zastąpić Eloquent - Doctrine.
Omenomn
Ta klasa abstrakcyjna nie ma kodu, jest pusta, co zaprzecza całej gadaninie coma i pythona na temat klas abstrakcyjnych.

Folder App\Http\Request\Request.php - Laravel 5.2.

Napisz coś lepszego i wtedy się wymądrzaj, bo jak na razie wolę czerpać wzorce z Laravel niż słuchać przemądrzałego gościa, który jakby pewnie pokazał jakiś kod projektu, to by była taka sieka, że głowa boli.
kapslokk

Myślisz, że takie obrazki wzięły się znikąd?
Pyton_000
Cytat(Omenomn @ 24.01.2017, 08:36:26 ) *
Ta klasa abstrakcyjna nie ma kodu, jest pusta, co zaprzecza całej gadaninie coma i pythona na temat klas abstrakcyjnych.


Po primo to nie "pythona". Szanujmy się.
Po secundo to zacytuj mi moją wypowiedź w które powiedziałem że klasa abstrakcyjna nie może być pusta.
mrc
@Omenomn

Uparty jesteś, niestety nie w tą stronę co trzeba. Jak za kilka lat przeczytasz swoje posty, to wstyd Ci się zrobi smile.gif

Wzorców projektowych nie powinieneś brać ani z Laravela, ani z Symfony. Wzorce projektowe po prostu są. Były przed Laravelem i przed Symfony. Ty po prostu zamykasz się co do jednego oczywistego i najwspanialszego frameworka.

Laravel, mimo że zaczyna być frameworkiem od całego web, zaczynając od backendowego mvc po front, dalej jest tylko Laravelem. Za kilka lat może znudzić Cię webmasterka (bo na dłuższą metę jest nudna). Będziesz szukał pewnie programowania innych rzeczy. W czym Ci tu pomoże wzór Laravela? W niczym. Miałem kiedyś krótki epizod z chłopakiem, który znał odrobinę języków microsoftowych. Kodowaliśmy chwilę w php. Zrobił sporą sieczkę i tłumaczył jeszcze, że tak się robi, bo te języki które zna tak działały. Oczywiście, wymyślał coś na około mvc, byle by nie mvc. Projektu nie udało się postawić, bo chłopak nie umiał sobie poradzić ze swoim tworem w nowych warunkach (web).

Może w chwili obecnej, kiedy pracujesz jako programista Laravel w firmie, jest Ci dobrze z tym co robisz i jak robisz. Życie i selekcja naturalna na pewno pokażą Ci, jak daleki jesteś od ideału developera.

PS. Sam kiedyś byłem bojówkarzem. PHP był dla mnie najlepszym językiem, a Java i języki kompilowane to zło. Perspektywa czasu mi pokazuje, że po prostu głupi byłem smile.gif.
com
Omenomn sorry ale to Tobie się wydaje, że wiesz wszystko najlepiej. Ja tylko podałem Ci definicje klasy abstrakcyjnej, która znajdziesz wszędzie. Jakbyś pisał w językach typu c++ to byś wtedy ją zapewne dobrze znał. A co do kodu wspaniałego frameworka, spójrz na to co się z tą klasa która nie miała sensu dzisiaj stało. Dziś jej już nie ma. A do każdej klasy możną sobie dopisać abstract, ale to nie znaczy, że to czyni każdą klasę abstrakcyjną.


A jak się chwile zastanowić, to co ona niby dawała, no nic bo wystarczyło by rozszerzać FormRequest. Ale wierz sobie dalej, że Taylor Otwell, nie może się mylić, chociaż jak sobie poczytasz historie jego i Laravel, to jak już mówiłem są tam pewne błędy w architekturze i jedyne rozwiązanie to nie używać tego, czego przykładem może być chociażby Eloquent, który implementuje Active record, to też wzorzec, ale nie jest on dobrym pomysłem.

Jednakże myślę, że już dalsza dyskusja nie ma sensu, bo stworzyłeś swój kod "doskonały" i próbujesz go obronić ja to rozumiem, jednakże jest on daleki od ideału i każdy Ci to powie, ja też wcale nie twierdze, ze moja implementacja to jedyna słuszna.
daro0
Aż do takich wniosków typu czy tam są błędy to bym nie dochodził. AR czy tam Singleton są uważane co prawda za przestarzałe, jednak z AR prawdę mówiąc dość wygodnie się pracuje, zwłaszcza dzięki tym relacjom has many, has one, belongs to. Dodatkowo mogę sobie np. w prosty sposób np. zaimplementować filtry, czyli np. automatyczny hash hasła przy zapisie danych do modelu User, również walidacje danych. Jasne że się można przyczepić do niezgodności z SRP ale to już inna sprawa. Bo podejrzewam że gdybym się zastanawiał nad tym wszystkim, to projekt który mam skończyć w jakimś określonym terminie to bym skończył znacznie później, zaliczając przy tym sporą obsuwę.

Ale to jest pryszcz. Wystarczy sobie porównać L 4.2 vs. L.5.3 żeby dojść do tego jak duże są między nimi różnice i jakie to ma przełożenie na praktykę. I tylko jestem ciekaw jak będzie wyglądać v. 6.x Laravela, bo znowu mogą być takie zmiany, że już port nie będzie taki prosty choć na dzień dzisiejszy L 5.3 można uważać za OK.
com
Zanim zaczniesz rzucać następnym razem nie słuszne oskarżenia to się zastanów:

Chciałeś kod "frameworka", samego kodu udostępnić nie mogę bo jest to zamknięte oprogramowanie, ale mogę dać światło na strukturę:



Użycie:


Wcale nie potrzebuje Laravela czy Symfony, żeby pisać dobry czysty kod, który można wykorzystać w wielu projektach, a te frameworki wręcz w tym przeszkadzają, bo już z góry narzucają jedyną słuszną implementacje zgodną z ideą twórców.

Framework taki jak Laravel czy Symfony też mam, ale nie mam takiego community jak one, wiec się nie rozwija, bo nie mam na to czasu. Powstał tylko dlatego, że te wielkie nie maja w pełni uporządkowanego api i pewien balast ciągną za sobą z wersji na wersję, dlatego, że nie mogą zrobić nagle bc breaka, co zdarza się jednak w Laravelu, za co jest krytykowany. Przykład ta klasa abstrakcyjna była do 5.2, dziś już nie ma. Dodatkowo powstał on z myślą o php 7, a w nowych projektach gdzie używam tego co jest powyżej target mam na 7.1, wiec wykorzystuje tam to co w nowej wersji najlepsze. Na chwile obecną te duże natomiast mogą tylko wspierać 7, ale nie używać, bo okres zakończenia rozwoju php 5 minął dopiero na początku tego roku, ale został przesunięty do wydania z przed pięciu dni.

A wsparcie to jest problem, przykład doctrine/common:
lib/Doctrine/Common/Persistence/ObjectRepository.php

Jest to interfejs, który ma jedną z metod, o takiej definicji:
  1. public function findOneBy(array $criteria);

Wszytko ładnie ale doctrine od ładnych paru wersji ma już implementacje taką:
  1. findOneBy(array $criteria, array $orderBy = null)

Niestety PhpStorm nie widzi tego, bo interfejs nie ma drugiego parametru i nie podpowie, a co więcej podkreśli jako błąd, choć kod będzie działać
Jest to jednak nie do ruszenia, cytując:
Cytat
we have our hands tied on basically anything that involves changing interfaces


daro0 Ja się zgadzam może i to się podobać, choć ja osobiście używałem w jednym projekcie i bardzo szybko uznałem, że nie jest to droga, która chce iść. Ale powiem Ci, że to co uważasz za zalety u konkurencji z data mapperem można zrobić w podobny sposób równie szybko.
viking
A PhpStorm nie podpowiada jak mu wskażesz @param Klasa|Interface ?
com
viking Podpowiada, ale ObjectRepository to jest interfejs głęboko w core Doctrine i bezpośrednio ja go nigdzie nie wstrzykuje, wiec ciężko tym wspomóc, może komentarze inline by pomogły(nie pamiętam czy sprawdzałem), ale jak się tego dużo używa w różnych miejscach, to one zrobią bałagan w kodzie.

W sensie
  1. /** @var TYPE_NAME $foo */
  2. $foo->method($param);
viking
Według mnie dużo więcej szkody robi brak tych komentarzy. Jeśli Ty jesteś autorem kodu i dopiero co go pisałeś wtedy pewnie wiesz co tam podstawić. Ale już druga osoba, albo nawet ty po czasie, więcej czasu straci na poszukiwanie co powinna tam użyć. Trzeba podążyć śladami plików, przekopac się przez strukturę.
com
viking chyba się nie zrozumieliśmy, ideologicznie wygląda to tak:

  1. interface FooInterface
  2. {
  3. public function method(Bar $bar);
  4. }
  5.  
  6. class Foo : FooInterface
  7. {
  8. public function method(Bar $bar, $param)
  9. {
  10. // ...
  11. }
  12. }
  13.  
  14. class Example
  15. {
  16. protected $foo;
  17.  
  18. public function __construct(FooInterface $foo)
  19. {
  20. $this->foo = $foo;
  21. }
  22.  
  23. /**
  24.   * @param Bar $bar
  25.   */
  26. public function bar(Bar $bar)
  27. {
  28. /** @var Foo $foo */
  29. $this->foo->method($bar, 'param');
  30. }
  31. }
  32.  



i teraz pisanie tego:
/** @var Foo $foo */

wszędzie gdzie chce wywołać to średni pomysł, a użycie Doctrine raczej jest jasne np w Symfony.

PhpDoc jak najbardziej używam wszędzie, ale tamto tylko wspomaga PhpStorma, który nie widzi parametru, nie defakto programistę, który jak nie zajrzy do implementacji to nie będzie nawet wiedział, ze ta metoda ma 2 parametry.
viking
No tak, ale teraz przy kodzie:
  1. /**
  2.   * @var FooClass|FooInterface
  3.   */
  4. protected $foo;


Podpowiedź będzie taka

Po co się męczyć? Jednym klikiem mam przejście do klasy albo interface i pełną podpowiedź definicji.
com
viking Ok, tak owszem masz rację, widzę zły przykład, tak to defakto wygląda:

  1. //...
  2. /** @var EntityManager $em */
  3. $em = $this->getDoctrine()->getManager();
  4. /...


Ale teraz widzę to nic nie da, bo to zwraca EntityManager, a tamto jest w EntityRepository, czyli sprawdzałem i nic to nie dawało wink.gif

To co mówisz, dla własnego kodu się sprawdza ale dla biblioteki już niekoniecznie smile.gif

A tak wgl jakie IDE?
viking
Przy ORM zawsze są jakieś mniejsze lub większe problemy. Za dużo magii.
Netbeans od lat.
Pyton_000
Dla PHPStorm jest plugin do SF który podpowiada, jest tam też Doctrine zawarte więc nie ma bidy
com
Pyton_000 owszem jest, używam, ale to bierze z interfejsu, a on się nie zgadza z implementacja smile.gif wiec z stąd ten problem
Omenomn
Cytat
Jest klasa abstrakcyjna bo nadal nie możesz zrobić z niej instancji. Owszem debilne jest to rozwiązanie że nie musi mieć metod ale jest. Jest i działa. Ba nawet coś takiego zadziała


Pyton_000.

a to paplanina com

Cytat
Nie, przykład wprost z jednego z moich projektów, nigdzie w definicji klasy nie masz powiedziane, ze ona ma mieć jakieś metody. Inaczej jest z klasa abstrakcyjna, która ma mieć co najmniej jedną metodę czysto wirtualna/abstrakcyjną.


mrc
Cytat
Wzorców projektowych nie powinieneś brać ani z Laravela, ani z Symfony. Wzorce projektowe po prostu są. Były przed Laravelem i przed Symfony. Ty po prostu zamykasz się co do jednego oczywistego i najwspanialszego frameworka.


Nie biorę wzorców projektowych z Laravela, tylko wzoruję się na praktykach w nim stosowanych.
Jeśli jeszcze mi ktoś powie, że używanie frameworka nie uczy dobrych praktyk, to pozamiatacie system.

Cytat
Sam kiedyś byłem bojówkarzem. PHP był dla mnie najlepszym językiem, a Java i języki kompilowane to zło. Perspektywa czasu mi pokazuje, że po prostu głupi byłem


Nie wiem skąd wziąłeś to, że uważam php za najlepszy język.

Cytat
A jak się chwile zastanowić, to co ona niby dawała, no nic bo wystarczyło by rozszerzać FormRequest. Ale wierz sobie dalej, że Taylor Otwell, nie może się mylić, chociaż jak sobie poczytasz historie jego i Laravel, to jak już mówiłem są tam pewne błędy w architekturze i jedyne rozwiązanie to nie używać tego, czego przykładem może być chociażby Eloquent, który implementuje Active record, to też wzorzec, ale nie jest on dobrym pomysłem.


a choćby to, że nie musisz za każdym razem dodawać use xxx/xxx/xxx/xxx/FormRequest do nowego requesta walidującego formularz.

Cytat
Wcale nie potrzebuje Laravela czy Symfony, żeby pisać dobry czysty kod, który można wykorzystać w wielu projektach, a te frameworki wręcz w tym przeszkadzają, bo już z góry narzucają jedyną słuszną implementacje zgodną z ideą twórców.


Frameworki przeszkadzają... używanie bibliotek też jest pewnie beee.

Cytat
Omenomn sorry ale to Tobie się wydaje, że wiesz wszystko najlepiej.


Nie wiem, rozwijam się cały czas. Programowanie to taka dziedzina, w której człowiek się uczy całe życie.
Jednak potrafię ocenić, kiedy rozwiązanie spełnia moje oczekiwania na dzień dzisiejszy czy nie i czy jest w porządku oraz kiedy ktoś zgrywa kozaka i na mega zniuansowany problem znajduje szybką prostą odpowiedź, mimo, że taka nie istnieje.
daro0
Cytat(Omenomn)
Nie biorę wzorców projektowych z Laravela, tylko wzoruję się na praktykach w nim stosowanych.
Jeśli jeszcze mi ktoś powie, że używanie frameworka nie uczy dobrych praktyk, to pozamiatacie system.


Na dzień dzisiejszy, bo nie wiem co będzie za kilka lat to nie Laravel ale Symfony jest uważany (przynajmniej przez pewną społeczność) za taki, który zasługuje na miano najlepszego pod względem tych dobrych praktyk, co nie znaczy że jest jedynym, który można rozważać jeśli się pisze jakiś serwis, zwłaszcza jeśli w grę wchodzi szybkość jego tworzenia (tak żeby klient nie musiał czekać i można było szybko wystartować), jak i perspektywy związane z jego opanowaniem albo co bardziej istotne ogarnięciem całego tego projektu. Mówię o pracy samodzielnej.

Spróbuj napisać własny framework nie wzorując się na żadnym Laravelu ani na żadnym innym istniejącym frameworku, następnie wystaw to pod ocenę społeczności i spróbuj jeszcze wypromować i przekonać innych do korzystania z niego. Zakładam że dajesz jedną z licencji OS np. MIT czy tam BSD. Powodzenia. Tym bardziej że mogę Ci zagwarantować, że zawsze się znajdzie choć mały procent fanatyków albo własnych rozwiązań, albo istniejących frameworków.

mrc
@Omenomn

Cytat
Nie wiem skąd wziąłeś to, że uważam php za najlepszy język.


Opisałem to, jakim bojówkarzem ja byłem.
Omenomn
Zmieniając temat, jak u Was z tworzeniem kategorii? Mam na myśli dziedziczenie i wyświetlanie ich z zachowaniem dziedziczenia.
Używacie rekursywności? Potraficie użyć jednego zapytania mysql, żeby pobrać odpowiednie kategorie razem z ich dziećmi i wyświetlić np. w drzewiastym menu?

Pyton_000
nested set
com
no typowo, brak argumentów to zacznijmy personalne wycieczki.

Przeczytaj sobie definicje klasy abstrakcyjnej a potem rzucaj oskarżenia.

Cytat
Jeśli jeszcze mi ktoś powie, że używanie frameworka nie uczy dobrych praktyk, to pozamiatacie system.


Skąd Ty te teorie bierzesz. Frameworki nie powstają po to żeby Cie czegokolwiek uczyć. One maja za zadanie ułatwić pisanie kodu i jego utrzymywanie.

Cytat
a choćby to, że nie musisz za każdym razem dodawać use xxx/xxx/xxx/xxx/FormRequest do nowego requesta walidującego formularz.


No nie musisz use xxx/xxx/xxx/xxx/FormRequest ale musisz dla Request wiec to różnicy nie robi. No i autor zrozumiał, ze to nie ma sensu wiec to wywalił i teraz zmieniaj to wszędzie przy migracji.

Cytat
Frameworki przeszkadzają... używanie bibliotek też jest pewnie beee.


Nie jest bo poco wymyślać koło na nowo, ale trzeba dobierać narzędzia w zależności od problemu, nie wszędzie budowanie systemu w oparciu o framework sprawi, ze będzie on łatwy w utrzymaniu. Jakby tak było to Facebook/OLX/Allegro nie pisali własnych rozwiązań, bo przecież jest Laravel/Symfony czy co tam sobie jeszcze wybiorą.


Cytat
Jednak potrafię ocenić, kiedy rozwiązanie spełnia moje oczekiwania na dzień dzisiejszy czy nie i czy jest w porządku oraz kiedy ktoś zgrywa kozaka i na mega zniuansowany problem znajduje szybką prostą odpowiedź, mimo, że taka nie istnieje.


No właśnie kozaka to próbujesz zgrywać tu Ty, bo wszyscy Ci już powiedzieli, ze Twoje rozwiązanie nie rozwiązało Twojego problemu, ale mimo to nadal próbujesz udowodnić, że wszyscy się mylimy, że banda czworga się myli bo Ty lepiej wiesz czym jest dekorator.
Omenomn
Cytat
nested set

to jest kiepskie rozwiązanie testowałem kiedyś, trzeba stosować dużo zapytań, przy aktualizacjach i dodawaniu rekordów, plus łatwo rozwalić sobie całą strukturę.
Mam lepsze tongue.gif
com
Jakie?
Pyton_000
Cytat(Omenomn @ 26.01.2017, 19:14:11 ) *
to jest kiepskie rozwiązanie testowałem kiedyś, trzeba stosować dużo zapytań, przy aktualizacjach i dodawaniu rekordów, plus łatwo rozwalić sobie całą strukturę.
Mam lepsze tongue.gif

Tak, korzystałem i uważam że jest to jedne z nalepszych rozwiązań jeśli chodzi o struktury drzewiaste. Ale jak każde trzeba dobierać do potrzeb.
Argumentem za Nested Set jest to że 1 zapytaniem i to bardzo prostym jesteś w stanie wyciągnąć dowolną strukturę, czy to gałąź, czy to cały poziom, cokolwiek.
Owszem dodawanie/usuwanie/przenoszenie jest "skomplikowan" tylko trzeba sobie zadać pytanie jaki jest współczynnik odczytu kategorii do ich edycji.

W sumie to najlepsze i najbardziej elastyczne rozwiązanie.

PS. Również chcę zobaczyć te "lepsze" rozwiązanie.
Już było na forum kilku ludzi którzy próbowali przeforsować swoje bzdury bo uważają że są najlepsze/jedyne słuszne/bla blabla...
daro0
Cytat(Omenomn)
to jest kiepskie rozwiązanie testowałem kiedyś, trzeba stosować dużo zapytań, przy aktualizacjach i dodawaniu rekordów, plus łatwo rozwalić sobie całą strukturę.


A możesz napisać jaśniej, w jaki sposób można rozwalić tą całą strukturę? Zwłaszcza jeśli się używa transakcji?

Widzę że nawet pod KO3 coś znalazłem:
https://github.com/dfox288/kohana-nested-sets

I tak:

  1. CREATE TABLE `categories` (
  2. `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  3. `name` varchar(45) NOT NULL,
  4. `lft` int(10) UNSIGNED NOT NULL,
  5. `rgt` int(10) UNSIGNED NOT NULL,
  6. `level` int(10) UNSIGNED NOT NULL,
  7. `scope` int(10) UNSIGNED NOT NULL,
  8. PRIMARY KEY (`id`)
  9. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;


  1. class Model_Category extends ORM_Nested_Sets
  2. {
  3. protected $_table_name = 'categories';
  4. }


Dodawanie kategorii głównej

  1. $root = ORM::factory('Category');
  2. $root->name = 'Root';
  3. $root->make_root();


Dodawanie podkategorii:

  1. $root = ORM::factory('Category', 1);
  2.  
  3. $child1 = ORM::factory('Category');
  4. $child1->name = 'Child1';
  5.  
  6. $child2 = ORM::factory('Category');
  7. $child2->name = 'Child2';
  8.  
  9. $root->add_child($child1);
  10. $root->add_child($child2);


I wyświetlanie podkategorii dla kategorii głównej:

  1. $root= ORM::factory('Category', 1);
  2. $children = $root->get_children()->as_array();


Pod Laravela też napewno coś się znajdzie:
https://github.com/blt04/doctrine2-nestedset

Gdzie tu widzisz problemy?
Omenomn
Pobieram wszystkie rekordy zachowując ich kolejność uwzględniając zagłębienie używając dwóch funkcji jednej do obliczenia głębokości dziecka:
  1. CREATE FUNCTION check_depth (p_id INT)
  2. RETURNS INT DETERMINISTIC
  3. BEGIN
  4. DECLARE depth INT DEFAULT 0;
  5. WHILE p_id IS NOT NULL DO
  6. SELECT parent_id INTO p_id FROM menu_items where id = p_id;
  7. SET depth = depth + 1;
  8. END WHILE;
  9. RETURN depth;


kolejność:

  1. CREATE FUNCTION check_order(p_id INT, the_order VARCHAR(10)) RETURNS VARCHAR(10) DETERMINISTIC
  2. BEGIN
  3. DECLARE p_the_order INT;
  4. WHILE p_id IS NOT NULL DO
  5. SELECT menu_items.parent_id, IFNULL(menu_items.the_order, 0) INTO p_id, p_the_order FROM menu_items where id = p_id;
  6. SET the_order = CONCAT(p_the_order + 1, '.', the_order);
  7. END WHILE;
  8. RETURN the_order;



następnie sortuję sobie po polu sort, w którym wywołałem funkcję:
  1. (SELECT check_order(menu_items.parent_id, IFNULL(menu_items.the_order, 0) + 1)) AS sort


i mam kolejność rekordów imitującą drzewo:
root
- item 1
-- item 2
- item 3

Później lecę sobie rekurencyjnie po tablicy z rekordami zaczynając od tych, które mają parent_id == null;
Sprawdzam w pętli, czy istnieją dzieci, aktualnego rekordu, jeśli tak to zapisuję je do np. $item['children'] i dla każdego dziecka sprawdzam tak samo czy mają dzieci.
Czyli rekurencja, ale działając na jednej tablicy rekordów z tabeli, a nie wykonująca za każdym razem zapytania do bazy;

Nested set nie musi używać rekurencji, ale rozwiązanie, które przedstawiam jest na pewno o wiele szybsze niż wykonywanie przy każdym sprawdzaniu dzieci zapytania do bazy.

Porównując z nested set jest może odrobinę wolniejsze, jednak relacje w bazie danych są o wiele prostsze, a na szybkości nie traci wiele, bo wykonuje jedno zapytanie.

Cytat
Gdzie tu widzisz problemy?


a choćby zmienię sobie w jednym rekordzie w bazie zakres w jednej pozycji z lewej lub z prawej strony i mi się sypnie wszystko.
Chyba, że przechowuje się też parent_id, ale to jest wtedy dziwne rozwiązanie.

Z resztą nested set wywołuje rekordy imitując drzewo, więc Ja do tego używam dwóch funkcji sql.
Żeby dalej to wyświetlić np. w rozwijanym menu i tak trzeba to rekurencją ogarnąć bez względu czy to nested set czy nie.
Kwestia, czy zrobi się to w jednym zapytaniu.
daro0
Zrobiłem mały test.

1. Wygenerowanie 1000 losowych kategorii, każdy każdy rodzic ma po 10 dzieci, ich dzieci po 10 dzieci, łącznie drzewo do 2-go poziomu zagnieżdżenia.

  1. public function action_generate()
  2. {
  3. $t1 = microtime(true);
  4.  
  5. for ($i = 1; $i <= 10; $i++)
  6. {
  7. $root = ORM::factory('Category');
  8. $root->name = Text::random('alpha', 20);
  9. $root->make_root();
  10. for ($j = 1; $j <= 10; $j++)
  11. {
  12. $child1 = ORM::factory('Category');
  13. $child1->name = Text::random('alpha', 20);
  14. $root->add_child($child1);
  15. for ($k = 1; $k <= 10; $k++)
  16. {
  17. $child2 = ORM::factory('Category');
  18. $child2->name = Text::random('alpha', 20);
  19. $child1->add_child($child2);
  20. }
  21. }
  22. }
  23. $t2 = microtime(true);
  24. echo 'Generated 1000 tree nodes in ' . ($t2 - $t1) . ' s';
  25. }


Czas generowania tego 40 sekund, przy czym analizując kod tego rozszerzenia modułu ORM tam za każdym krokiem pętli jest begin transaction i commit.

I wyświetlenie drzewa (narazie nie wiem jak to zrobić w jednym zapytaniu):

  1. public function action_tree()
  2. {
  3. if (!Fragment::load('tree'))
  4. {
  5. $parents = ORM::factory('Category')
  6. ->where('level', '=', 0)
  7. ->find_all();
  8.  
  9. echo '<pre>';
  10.  
  11. foreach ($parents as $parent)
  12. {
  13. echo '-' . $parent->name . "\n";
  14. $children1 = $parent->get_children();
  15. foreach ($children1 as $child1)
  16. {
  17. echo ' --' . $child1->name . "\n";
  18. $children2 = $child1->get_children();
  19. foreach ($children2 as $child2)
  20. {
  21. echo ' ---' . $child2->name . "\n";
  22. }
  23. }
  24. }
  25.  
  26. echo '</pre>';
  27. Fragment::save();
  28. }
  29. }


Średni czas (za pierwszym razem, za drugim odczyt z cache) to był jakieś 0,3 s.

@Omenomn

To Twoje rozwiązanie będzie szybsze a jeżeli tak to o ile?

Omenomn
No sądzę, że o wiele mniej, ale nie mierzyłem szybkości zapytania i wykonania rekurencji na tablicach. Jak będę miał chwilę to przetestuję na takiej samej ilości rekordów i zagnieżdżeń jak podałeś.

Zmierzyłem czasy.
Mam 1110 rekordów, gdzie 10 rekordów ma po 10 dzieci i każde dziecko ma po 10 dzieci.
Samo zapytanie do bazy sortujące odpowiednio rekordy trwa: 0.3800 sekund(y)
Natomiast request do wygenerowanie z zapytania zagnieżdżonej odpowiednio tablicy trwa: 13949 ms, czy prawie 14 sekund.



Przy stu rekordach więcej jest spadek czasu o 25 sekund, porównując z czasami daro0

Musiałem trochę zmodyfikować funkcję i argumenty do sortowania, bo działało dobrze na liczbach pojedynczych, ale na wyższych już nie, dlatego, że było:

1
10
2,
a powinno być:
1
2
10,

jednak rozwiązałem ten problem funkcją lpad.

Rozwiązanie to ma nieograniczoną ilość zagnieżdżeń.
Zapytanie nie traci zupełnie na szybkości w porównaniu z nested set, a i tak żeby wyświetlić drzewo kategorii, trzeba przerobić również nested set na zagnieżdżona tablicę, no chyba, że jakoś się to ogarnie if-ami, ale nie wiem, czy to możliwe, kiedyś tak kombinowałem i chyba działało, ale zrezygnowałem z tego.

Testowane na serwerze lokalnym, na serwerze online było by pewnie szybciej.

Dodatkowo ten sposób sortowania kategorii rozwiązuje problem z eksportem i importem kategorii do tabeli.
Rozwiązanie pobierające rekursywnie rekordy z tabeli odpytując za każdym razem, pobiera rekordy w odpowiedniej kolejności, ale nie zastosuje się tego przy eksporcie rekordów z tabeli, bo jeżeli rodzic występuje w tabeli za dzieckiem, to mamy błąd klucza obcego i rekordy się nie dodadzą podczas importu.

Nested set rozwiązuje ten problem, ale moje rozwiązanie również biggrin.gif


Zrobiłem coś jeszcze bardziej hardkorowego i teraz taką samą zagnieżdżoną tablicę generuję w niecałe 2 sekundy. Totalny meksyk.



Zamiast rekurencji, ogarniam wszystko w jednej pętli biggrin.gif, to jest chyba najbardziej optymalne rozwiązanie jakie może istnieć tongue.gif
com
Tylko jedno pytanie jak się to ma do cache? nested set możesz sobie wrzucić to Twoje nie wiem, nested set ma stosunkowo szybkie odczyty wolne zapisy.
Omenomn
Chyba każdego selecta można wrzucić do cache z tego mi wiadomo z tym, że tutaj sam select trwa pół sekundy.
Ja nie używam cache zbyt często, ale raczej na pewno powinno się to dać wrzucić.

Niecałe dwie sekundy wygenerowania strony z requesta z tyloma rekordami z zagnieżdżeniem według mnie nie wymaga cache, ale to już indywidualna kwestia, czy ktoś chce jeszcze szybciej, czy to mu wystarczy.

Szczerze mówiąc nie spotkałem się nigdy z takim rozwiązaniem, jakie tu przedstawiam, więc chyba wymyśliłem innowację.

Prawdopodobnie czas ten też jest związany z działaniem Laravela.
Sam request bez żadnych obliczeń zwracający string 'ok' trwa 1141 ms, więc wygenerowanie drzewa wraz z zapytaniem to jedyne 1732 - 1141 = 591 ms.
Pół sekundy trwa zapytanie i stworzenie tablicy zagnieżdżonej.
com
Tak zapytanie owszem, ale samego fora już nie wrzucisz. To że coś będzie szybkie nie oznacza jeszcze że to jest najlepsze rozwiązanie. Bo taki kod musi być łatwo edytowalny, napisany tak zęby dało się go bez problemu zrozumieć i przetestować.
Omenomn
a Ty znowu zaczynasz...
Cytat
Tak zapytanie owszem, ale samego fora już nie wrzucisz. To że coś będzie szybkie nie oznacza jeszcze że to jest najlepsze rozwiązanie. Bo taki kod musi być łatwo edytowalny, napisany tak zęby dało się go bez problemu zrozumieć i przetestować.

Fora nie wrzucisz, ale wrzucisz przerobioną tablicę, po za tym nie trzeba cache przy takiej szybkości.
Uważam, że rozumienie kodu to też kwestia wiedzy, owszem zapytanie sql zawiera dwie funkcje i zagnieżdżone selecty z ifami, ale jak ktoś tego nie rozumie to jego sprawa.
Nie wiem o co Ci chodzi z tym testowaniem, każdą funkcjonalność testuję czy działa, przecież nie zostawię w aplikacji funkcjonalności bez jej sprawdzenia.

Nie mam zamiaru nikogo do tego przekonywać, podobnie jak do wcześniejszego rozwiązania.
Oba sprawdzają się całkowicie, a to, że ktoś kocha nested set, czy tam inne, to jego sprawa.

Stworzyłem rozwiązanie tak szybkie, że nie ma potrzeby go przyśpieszać według mnie tongue.gif
Pyton_000
Niecałe 2s. to wg. Ciebie mało? To strasznie dużo zwłaszcza na 1 operację i tym bardziej powinna lecieć w cache...
nospor
Cytat
Mam 1110 rekordów, gdzie 10 rekordów ma po 10 dzieci i każde dziecko ma po 10 dzieci.
Samo zapytanie do bazy sortujące odpowiednio rekordy trwa: 0.3800 sekund(y)

Zrobiłem coś jeszcze bardziej hardkorowego i teraz taką samą zagnieżdżoną tablicę generuję w niecałe 2 sekundy. Totalny meksyk.


Stworzyłem rozwiązanie tak szybkie, że nie ma potrzeby go przyśpieszać według mnie


Tja..... 1100 rekordow i az "tylko" 0.38 sekundy... Normalnie torpeda...
Dla takiej ilosci rekordow zapytanie powinno sie wykonywac 0.0038 sekundy lub szybciej

Sorki, twoje rozwiazanie jest kiepskie. Dziala bo dziala bo masz malo danych. Przy wiekszej liczbie danych szlag wszystko trafi
I nie, nie promuje nested set... Ja promuje drzewka IP, to jest dopiero meksyk wink.gif

ps: i wiesz czemu tak sie uparles tej swojej "torpedy" ? Bo poprostu nie ogarniasz lepszych rozwiazan. wink.gif Ale cicho sza, bo ktos sie jeszcze dowie wink.gif
Omenomn
To jest zapytanie pobierające zagnieżdżone kategorie, chyba zapomnieliście o tym i tworzące zagnieżdżoną tablicę.
Zazdrość kipi gęsta!! Nie wierzę biggrin.gif

daro0 przedstawił swoje i trwało 40 sekund, przy normalnym pobieraniu rekordów rekursywnie.
Nested set może działać podobnie szybko, ale dane są o wiele bardziej wrażliwe.

O drzewkach ip nie słyszałem, ale z tego co widzę mają statyczną ilość zer 0000000000.0000000002.0000000005 więc jest ograniczone zagnieżdżenie, a u mnie nie ma ograniczenia i nic się nie sypnie, bo dane nie są ani trochę wrażliwe.
Nawet jak będę grzebał bezpośrednio w tabeli i zmienię w rekordzie rodzica, czy kolejność to nie ma żadnego wpływu na zależności i inne rekordy.

Mam rozwiązanie lepsze niż standardowa rekurencja, lepsze niż nested set, a Wy twierdzicie, że jest kiepskie.
Żałosne i tyle. Zazdrość i próby budowania ego.

Cytat
Niecałe 2s. to wg. Ciebie mało? To strasznie dużo zwłaszcza na 1 operację i tym bardziej powinna lecieć w cache...

Cytat
Tja..... 1100 rekordow i az "tylko" 0.38 sekundy... Normalnie torpeda...
Dla takiej ilosci rekordow zapytanie powinno sie wykonywac 0.0038 sekundy lub szybciej


Jak można porównywać pobieranie kategorii selectem z zachowaniem zagnieżdżonej kolejności ze zwykłym selectem pobierającym rekordy, to jest szczyt ignorancji i głupoty.

Niech ktoś zrobi to szybciej...
Pyton_000
Spoko podejmuję wyzwanie.

Powiedz jaki ma być wynik, podaj średni czas wykonywania.
Najlepiej daj dump z SQL + kod żeby można było to sobie samemu odpalić i porównać wyniki.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.