[PHP] Uniwersalne tworzenie obiektów klas o nazwach ze string'a |
[PHP] Uniwersalne tworzenie obiektów klas o nazwach ze string'a |
27.05.2020, 09:11:20
Post
#1
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Sorry, jeśli odpowiedź na moje pytanie jest banalna. Jednak szukam w Google i nie mogę nic znaleźć.
Chcę przekazywać parametrem metody stringi (np. 'NewClass'), na podstawie których będę tworzyć obiekty (np. $object = new NewClassModel()). Potem chcę te obiekty zwracać (return $object). Chodzi o to, aby to było uniwersalne. Jak to prosto zrobić? |
|
|
27.05.2020, 09:37:15
Post
#2
|
|
Grupa: Moderatorzy Postów: 36 446 Pomógł: 6292 Dołączył: 27.12.2004 |
-------------------- "Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista "Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer |
|
|
27.05.2020, 09:51:11
Post
#3
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Działa. Aż się zawstydziłem.
|
|
|
27.05.2020, 10:03:51
Post
#4
|
|
Grupa: Moderatorzy Postów: 36 446 Pomógł: 6292 Dołączył: 27.12.2004 |
wybacz moje glupie pytanie ale po co ci to? Co ty chcesz tutaj zrobic bardziej uniwersalnego? Boje sie, ze cos probujesz przekombinowac
-------------------- "Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista "Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer |
|
|
29.05.2020, 09:59:46
Post
#5
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Chciałem zrobić odwołania do modelu podobnie, jak jest w Symfony. Np. coś w tym stylu:
Kod $sr = $model->getRepository('Site'); $sr->setMethod($id, $varible); Ale właśnie zauważyłem, że to nie jest najlepsze rozwiązanie. W Symfony jest używany menadżer: Kod $em = $this->getDoctrine()->getManager(); $em->getRepository('App:Site')->setMethod($id, $varible); Chodzi mi o to, aby nie wstrzykiwać do kontrolera kilku obiektów z repozytoriami (np. dla UserRepository, SiteRepository oddzielnie), ale aby to zrobić uniwersalnie. Tworzyć jeden obiekt (np. w index.php). Połączyć się z bazą. Wstrzyknąć go do kontrolera i potem używać tego repozytorium, które jest mi akurat potrzebne. Jednak widzę, że tak tego nie zrobię. Prosiłbym o sugestie, jak to zrobić lepiej. Podobnie planuję postępować z kontrolerami. W index.php, na podstawie parametru z .htaccess, tworzyć uniwersalnie obiekt kontrolera, który jest mi akurat potrzebny. Przekazywać mu metodą obiekt mojego modelu, tablicę wyników z formularza i sesję. Ok. Wersje robocze klas wyglądają na chwilę obecną tak: Kod <?php declare(strict_types=1); namespace App\Core; use App\Core\Model; class Controller { public function getManager(): object { $model = new Model(); $model->dbConnect(); return $model; } } Kod <?php declare(strict_types=1); namespace App\Core; use App\Core\DataBase; class Model extends DataBase { public function getRepository(string $name): object { $class = $name . 'Repository'; return new $class; } } Kontrolery mają rozszerzać klasę Controller. Przykładowe użycie: Kod $mm = $this->getManager(); $mm->getRepository('Site')->setMethod($id, $variable); $variable = $mm->getRepository('Site')->getMethod($id); Może tak pozostać? Prosiłbym o ocenę kodu i uwagi. PS Właśnie zauważyłem, że jest jeszcze jedne problem. Da się użyć jakiegoś uniwersalnego "use" dla moich klas z repozytorium? Bo teraz wywali błąd... |
|
|
29.05.2020, 10:00:10
Post
#6
|
|
Grupa: Moderatorzy Postów: 36 446 Pomógł: 6292 Dołączył: 27.12.2004 |
Ok, takie uzycie dynamicznych nazw klas ma sens.
Nie mniej jednak naduzywasz typu "object" a tym samym powodujesz ze twoje metody moga zwracac praktycznie wszystko a nie powinny. metoda model ma zwracac Model a nie dowolny object. Tak samo getRepository() ma zwracac obiekt repository a nei dowolny obiekt. Utworz interfejsy i mow ze metody maja zwracac obietky tych interfejsow -------------------- "Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista "Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer |
|
|
29.05.2020, 12:19:08
Post
#7
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Widzę, że źle zrozumiałem ostatnią zasadę SOLID. Zasada odwrócenia odpowiedzialności (ang. dependency inversion principle) mówi, iż wszystkie zależności powinny w jak największym stopniu zależeć od abstrakcji, a nie zależeć od konkretnego typu. Doszedłem do wniosku, iż typ object to najlepiej zapewnia. Dlatego stosowałem object praktycznie wszędzie. Rozumiem, iż mam stosować interfejsy. I tu mam pytanie: Po czym mogę określić, czy mam użyć typu object, interfejsu bądź konkretnej klasy?
Co do mojego kodu. Czy każdorazowe używanie, przy każdym wywołaniu dowolnej metody z repozytorium, metody getRepository() jest poprawne? Chodzi mi o to, iż wielokrotnie tworzony jest obiekt tego samego repozytorium... I jeszcze: Gdzie powinienem umieszczać interfejsy? Mogę je dodawać zbiorczo do katalogu Interface? |
|
|
29.05.2020, 12:24:54
Post
#8
|
|
Grupa: Moderatorzy Postów: 36 446 Pomógł: 6292 Dołączył: 27.12.2004 |
Cytat Po czym mogę określić, czy mam użyć typu object, interfejsu bądź konkretnej klasy? Object wtedy, gdy naprawde bedziesz zwracal totalnie rozne obiekty w zaden sposob ze soba nie powiazane. W przeciwnym wypadku raczej zawsze interfejsy. Cytat Co do mojego kodu. Czy każdorazowe używanie, przy każdym wywołaniu dowolnej metody z repozytorium, metody getRepository() jest poprawne? Chodzi mi o to, iż wielokrotnie tworzony jest obiekt tego samego repozytorium... Dobrze by klasa z ta metoda miala wewnetrzny cache (tablice) ktore bedzie pamietac raz utworzony repository Cytat jeszcze: Gdzie powinienem umieszczać interfejsy? Mogę je dodawać zbiorczo do katalogu Interface? Jak tak robie.
-------------------- "Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista "Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer |
|
|
1.06.2020, 09:54:53
Post
#9
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Słowo "Interface" jest w PHP zajęte. Chyba nie mogę w takim katalogu przechowywać wszystkich moich interfejsów. Jak więc najlepiej będzie nazwać folder z interfejsami? Gdzie je przechowywać?
I jeszcze nie wiem, jak nazywać interfejsy w PHP. Np.: RepositoryInterface czy iRepository? Jakie nazewnictwo jest poprawne? |
|
|
1.06.2020, 09:56:33
Post
#10
|
|
Grupa: Moderatorzy Postów: 36 446 Pomógł: 6292 Dołączył: 27.12.2004 |
katalog Contracts
-------------------- "Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista "Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer |
|
|
2.06.2020, 11:25:30
Post
#11
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Ok. Nikt nie odpowiedział na moje pytanie odnośnie interfejsów w oddzielnym temacie, więc zrobiłem to na czuja. PHP nie wywala błędów i niby wszystko działa ok, ale nie jestem pewny, czy jest to napisane fachowo...
Kod <?php declare(strict_types=1); namespace App\Repository; use App\Contract\{ModelInterface, RepositoryInterface}; class TestRepository implements RepositoryInterface { protected ModelInterface $model; public function __construct(ModelInterface $model) { $this->model = $model; } // [...] } Kod <?php declare(strict_types=1); namespace App\Core; use App\Contract\ModelInterface; use App\Core\Model; class Controller { protected Model $model; public function getModelManager(): ModelInterface { if (!isset($this->model)) { $this->model = new Model(); $this->model->dbConnect(); } return $this->model; } } Kod <?php declare(strict_types=1); namespace App\Core; use App\Contract\{ModelInterface, RepositoryInterface}; use App\Core\DataBase; class Model extends DataBase implements ModelInterface { protected array $repository; public function getRepository(string $name): RepositoryInterface { $class = 'App\\Repository\\' . $name . 'Repository'; $this->repository[$name] = new $class($this); return $this->repository[$name]; } } Kod <?php declare(strict_types=1); namespace App\Contract; use App\Contract\ModelInterface; interface RepositoryInterface { public function __construct(ModelInterface $model); } Kod <?php
declare(strict_types=1); namespace App\Contract; use App\Contract\RepositoryInterface; interface ModelInterface { public function getRepository(string $name): RepositoryInterface; } |
|
|
2.06.2020, 11:55:43
Post
#12
|
|
Grupa: Zarejestrowani Postów: 6 365 Pomógł: 1114 Dołączył: 30.08.2006 Ostrzeżenie: (0%) |
Trochę mało uniwersalne jak dla mnie. Już samo ustawianie $class = 'App\\Repository\\' . $name . 'Repository'; eliminuje ładne użycie ::class. Nie bardzo rozumiem czemu controller tworzy połączenie z bd dla modelu i dlaczego jest ustawiany model a nie repo. Ale nawet jeśli co gdyby chcieć użyć 2 modele? Co jeśli chciałbyś miec 2 instancje modelu (trochę ciężko ustalić co wg ciebie znaczy model - )? Albo co jeśli model to nie zwykła baza tylko np elasticsearch?
-------------------- |
|
|
2.06.2020, 13:14:44
Post
#13
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Cytat Trochę mało uniwersalne jak dla mnie. Już samo ustawianie $class = 'App\\Repository\\' . $name . 'Repository'; eliminuje ładne użycie ::class. Z zapisem ::class spotkałem się przy programowaniu w Symfony, ale zbytnio jeszcze nie wiem, jak tego używać samemu. Muszę doczytać... Cytat Nie bardzo rozumiem czemu controller tworzy połączenie z bd dla modelu i dlaczego jest ustawiany model a nie repo. Z tym tworzeniem obiektu db z poziomu kontrolera spotkałem się we framework'u Symfony. Zrobiłem tak, aby było niemal identyczne wywołanie metod. W Symfony z poziomu kontrolera pobierane jest Doctrine i dalej Menadżer Encji. Z menadżera pobierane są Repozytoria i dalej wywoływane ich metody. Co do nazwy klasy Model. Lepiej będzie, aby klasa zarządzająca repozytoriami nazywała się po prostu Repository? Cytat Ale nawet jeśli co gdyby chcieć użyć 2 modele? Co jeśli chciałbyś miec 2 instancje modelu (trochę ciężko ustalić co wg ciebie znaczy model - )? Model odpowiada u mnie za jednokrotne połączenie z bazą danych i zarządzanie repozytoriami. Mogę mieć jeden obiekt modelu (menadżera), który tworzy i zwraca dowolną ilość repozytoriów. Tak jest w Symfony... Cytat Albo co jeśli model to nie zwykła baza tylko np elasticsearch? Czyli jak? Starczy, że zmienię nazwę klasy Model (mojego menadżera repozytoriów) na np. Repository i będzie już dobrze (brak konflików)? Bo zbytnio chyba nie do końca zrozumiałem, w czym tkwi problem. Chodzi o samą nazwę klasy Model? |
|
|
2.06.2020, 13:18:51
Post
#14
|
|
Grupa: Zarejestrowani Postów: 6 365 Pomógł: 1114 Dołączył: 30.08.2006 Ostrzeżenie: (0%) |
To pytanie pomocnicze? Po co tworzysz jakieś własne hokus pokus zamiast użyć poprawnie Symfony? Skoro i tak robisz kopię S. Popracuj z jakimś większym FW, zobacz jak robi się pewne rzeczy, zdobądź doświadczenie.
-------------------- |
|
|
2.06.2020, 13:37:44
Post
#15
|
|
Grupa: Zarejestrowani Postów: 81 Pomógł: 0 Dołączył: 3.08.2017 Ostrzeżenie: (0%) |
Cytat Po co tworzysz jakieś własne hokus pokus zamiast użyć poprawnie Symfony? Skoro i tak robisz kopię S. Zamierzam docelowo (zawodowo) programować w gotowych frameworkach, ale pomyślałem, że fajnie byłoby zrobić coś podobnego samemu. Tylko mój framework miał być dużo bardziej prosty w zapisie. Takie minimum kodu i podobny efekt końcowy. Cytat Popracuj z jakimś większym FW, zobacz jak robi się pewne rzeczy, zdobądź doświadczenie. Ok. Poprawię ten mój framework po swojemu i będę powoli rozwijał wraz z rosnącą wiedzą. Generalnie wszystko można zapisać na miliony sposobów i rozchodzi się tylko o przestrzeganie pewnych wytycznych oraz ogólnie przyjętych zasad. |
|
|
2.06.2020, 14:18:35
Post
#16
|
|
Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) |
Zamiast tracić czas na tworzenie własnego FM skupiłbym się raczej na popraacowaniu nad architekturą. Poczytaj o DDD, o CQRS, kolejki, middleware, poznaj smaczki SF żebyś wiedział jak działa. Poznaj Doctrine a zobaczysz jak działa Proxy, zobaczysz jak się zachowuje.
Na prawdę tworzenie własnego FW w tych czasach to marnowanie czasu. Chyba że robisz to sam dla siebie od tak żeby się pobawić. |
|
|
Wersja Lo-Fi | Aktualny czas: 19.04.2024 - 03:52 |