Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [PHP] Uniwersalne tworzenie obiektów klas o nazwach ze string'a
eerie
post 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ć?
Go to the top of the page
+Quote Post
nospor
post 27.05.2020, 09:37:15
Post #2





Grupa: Moderatorzy
Postów: 36 440
Pomógł: 6290
Dołączył: 27.12.2004




a
  1. $zm = 'NewClass';
  2. $object = new $zm;

nie dziala?


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post
eerie
post 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. smile.gif
Go to the top of the page
+Quote Post
nospor
post 27.05.2020, 10:03:51
Post #4





Grupa: Moderatorzy
Postów: 36 440
Pomógł: 6290
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

Go to the top of the page
+Quote Post
eerie
post 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. wink.gif

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. smile.gif

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...
Go to the top of the page
+Quote Post
nospor
post 29.05.2020, 10:00:10
Post #6





Grupa: Moderatorzy
Postów: 36 440
Pomógł: 6290
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

Go to the top of the page
+Quote Post
eerie
post 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?
Go to the top of the page
+Quote Post
nospor
post 29.05.2020, 12:24:54
Post #8





Grupa: Moderatorzy
Postów: 36 440
Pomógł: 6290
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

Go to the top of the page
+Quote Post
eerie
post 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?
Go to the top of the page
+Quote Post
nospor
post 1.06.2020, 09:56:33
Post #10





Grupa: Moderatorzy
Postów: 36 440
Pomógł: 6290
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

Go to the top of the page
+Quote Post
eerie
post 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] questionmark.gif= 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;
}
Go to the top of the page
+Quote Post
viking
post 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?


--------------------
Go to the top of the page
+Quote Post
eerie
post 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?
Go to the top of the page
+Quote Post
viking
post 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.


--------------------
Go to the top of the page
+Quote Post
eerie
post 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. wink.gif
Go to the top of the page
+Quote Post
Pyton_000
post 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ć.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.03.2024 - 11:03