Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

2 Stron V  < 1 2  
Reply to this topicStart new topic
> [PHP] Logowanie, zwrot/wypozyczenie ksiazek OOP - mocno początkujący
nospor
post 20.11.2019, 10:53:34
Post #21





Grupa: Moderatorzy
Postów: 34 870
Pomógł: 5802
Dołączył: 27.12.2004




Jest zdecydowanie lepiej.

echo View::renderTemplate('mysite/borrow.html', ['books' => Library::getBooks()]);
echo raczej jest tu zbedne

Jestes bardzo nie konsekwenty i tworzysz cala mase klas, ktore w polowie sobie obiektami a w polowie maja metody statyczne. Ok, czasami metoda statyczna moze i sie przydac, ale tutaj u ciebie w wiekszosci wypadkow jest to zle zaprojekotwane

Uzywaj === oraz !==

Okreslaj wszedzie typy a nie tylko w polowie plikow

Zainteresuj sie narzedziami do statycznej analizy kodu, np phpstan. Odwala za ciebei polowe roboty.

if ($code = '500') {
Ty w ogole testujesz kod, ktory piszesz? Juz nie mowie nawet o phpunit ale o zwyklym manualnym tescie...

Staraj sie optymalizowac swoj kod, np
private function getNamespace(): string
{
$namespace = "App\Controllers\\";
return $namespace;
}

mozna poprostu napisac
private function getNamespace(): string
{
return "App\Controllers\\";
}
Nie ma sensu tworzyc zbednych zmiennych niczego nie wnoszacych

  1. class Config
  2. {
  3. const DB_HOST = 'localhost';
  4. const DB_NAME = 'librarymvc';
  5. const DB_USER = 'root';
  6. const DB_PASSWORD = '';
  7. }

Powiedzmy ze ja tez pracuje z twoim kodem. jednak moja baza ma inny dostep. Jak ja to zmienie teraz u siebie? Przeciez wlasnie nadpisze twoje pliki z git.

I zmiluj sie i nie komituj zawartosci folderu VENDOR


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

Najlepsze kawałki programistyczne || Dowcipy o informatykach || Forum PHP dla opornych
Klasy: Pager (stronicowanie) | Cache | ShoutBox (Chat) | Widok | Ładne url'e

"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
athabus
post 21.11.2019, 08:36:44
Post #22





Grupa: Zarejestrowani
Postów: 898
Pomógł: 46
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


No prosze a już myślałem, że się poddałeś ;-)

Kod wygląda o niebo lepiej niż pierwsza wersja - wreszcie zaczyna przypominać jakąś strukturę używaną w 21 wieku, więc widać że czasu nie zmarnowałeś. Ale nie będę Ci tu słodził bo nie po to tu piszesz.

Moje uwagi
- brak konfiguracji o czym pisał nospor - rzeczy, które mogą się zmieniać powinny być wydzielone do osobnego miejsca. Np. plik yaml + obiektowy wraper na to pozwalający odczytywać dane konfiguracyje

- jak używasz static to na 99% możesz być pewien, że popełniasz błąd projektowy. Static to taki nowy stan globalny i z aplikacji powinien zniknąć, bo w ten sposób ukrywasz niepotrzebnie zależności. Wszystkie zależności powinny być wstrzykiwane przez konstruktor choćby dlatego, że wtedy widzisz, ze robi się ich w pewnym momencie za dużo i jest pora na refactoring. Tak więc moja rada - usuń wszystkie odwołania static.

- brakuje mi w Twoim kodzie obiektów Request / Response. Echo powinno pojawić się w kodzie aplikacji tylko raz, gdy renderujesz Response. U ciebie tekst jest printowany w kontrolerach, autoryzacji itp. Masz różne dziwne kontrukcje typu przekierowanie headerem w kontrolerze itp... Tak nie powinno być - powinieneś mieć obiekt Response - najlepiej w kilku odmianach typu "NotAuthorizedResposne / NotFoundResponse / RedirectResponse" itp. Contoller powinien zwracać taki Response i front controller albo powinien decydować co dalej z tym zrobić. W ten sposób bedziesz miał piękne polimorficzne kontrollery, które zawsze będą zachowywać się tak samo, czyli zwracać obiekt ResponseInterface lub AbstractResponse. Ewentualnie zamiast zwracać niektóre Respony można rzucać wyjątki typu NotFoundException i przechwytywać je we frontkontolerze (gdyby go miał).

- Brakuje mi obiektu FrontController - > to ten obiekt powinien inicjować Request, Router i obsłgiwać Response zwrócony z kontrolera

- Pytałeś o dziedziczenie po kontrolerze - tutaj jak najbardziej moim zdaniem ma to sens, bo kontroler ma dużo kodu, który jest wszędzie potrzebny, więc dziedziczenie jest uzasadnione.Warto byłoby aby była to klasa abstrakcyjna.

- kod ciągle nie jest zgodny z PSR

Ogólnie błędów jest sporo więcej, ale jak poprawisz to + to co napisał nospor możemy iść dalej ;-)
Gratki za postępy.

Go to the top of the page
+Quote Post
mrpickles
post 21.11.2019, 16:45:44
Post #23





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 14.10.2019
Skąd: Białystok

Ostrzeżenie: (0%)
-----


Dzięki za uwagi:)

1) Powalczę z gitem - zamiast nie śledzić więcej vendor, przypadkowo usunąłem. Przerobie tutorial i to naprawie.
2) Odnośnie Config - Propel/Doctrine to coś czym powinienem się zainteresować czy zbłądziłem? Temat jest mi zupełnie obcy.
3) Co do static poczytałem i wiem o co już chodzi - przerobie na Dependency injection.
4) PHPStan zainstalowałem, znalazł kilka niespójności - dzięki za informacje o czymś takim.
5) Co do front controllera jestem trochę zmieszany, zgłębiam temat i coś świta, jednak nie znalazłem żadnych dokończonych wątków na ten temat:)
Przeglądałem sporo poradników, jednak większość podstawowych MVC było skróconych tylko do rutera. Z tego co zebrałem w całość:



Czy chodzi o takie przebieg wydarzeń? Front controller przekazuje do Routera request, ten je rozbraja i zwraca controller,action, params. Następnie frontcontroller pełni też rolę dispatchera i wywołuje odpowiednie kontrolery. Nie generują one renderTemplate tylko generują response, która trafia do front controller i on dopiero odpala renderTemplate etc? Jeśli tak, brzmi abstrakcyjnie. Tutoriale o klasach animal nie wiele mają z tym wspólnego smile.gif

  1. Front Controller -> Request ->Dispatcher -> Controler -> Response ->front Controller
  2. || /\
  3. \/ ||
  4. router


Ten post edytował mrpickles 21.11.2019, 16:46:45
Go to the top of the page
+Quote Post
athabus
post 21.11.2019, 17:19:04
Post #24





Grupa: Zarejestrowani
Postów: 898
Pomógł: 46
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Tak w telegraficzny skrócie, to to co zaproponowałeś wygląda jak w miarę sensowny przebieg.
Front controller odpala Router, ten z kolei na podstawie danych z Request dispatchuje przebieg do odpowiedniego kontrolera.
Kontroler zwraca Response. W takiej minimalistycznej wersji Response powinno zawierać:
- body (do body renderujesz np szablon w kontrolerze)
- headery (np. content-type)
- status code (np. 200/404 itd)
Front controller po otrzymaniu responsa "wysyła" go do przeglądarki (lub innego klienta) - zazwyczaj coś w stylu $response->send() - metoda send zajmuje się wyświetleniem / ustawieniem hederów itp. Czyli np. jak response będzie 301 to $response->send() wykona przekierowanie, a jak 200 to wyświetli zawartość w zależności od content-type (bo przecież to może być html ale też np. json lub xml).

Obiektów response zazwyczaj jest kilka i mają one wspólny interfejs - w ten sposób jak za miesiąc Twoja apka będzie musiał w jakiejś akcji zwrócić json zamiast html to po prostu utworzysz sobie JsonResponse implementujący interfejs Response i nic nie będziesz musiał zmieniać w szkielecie.

To jest własnie kluczowa sprawa w OOP żeby tworzyć strukturę, która do rozszerzenia nie wymaga edycji już istniejącego kodu. Jeśli twój front Kontroller będzie akceptował generyczny Response to mu wszystko co się dzieje w $response->send().

Oczywiście to tylko jedno z możliwych podejść.
Go to the top of the page
+Quote Post
viking
post 21.11.2019, 18:53:53
Post #25





Grupa: Zarejestrowani
Postów: 5 430
Pomógł: 927
Dołączył: 30.08.2006

Ostrzeżenie: (0%)
-----


Możesz też zmienić podejście i poczytać o https://www.php-fig.org/psr/psr-15/


--------------------
Go to the top of the page
+Quote Post
mrpickles
post 5.12.2019, 22:28:48
Post #26





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 14.10.2019
Skąd: Białystok

Ostrzeżenie: (0%)
-----


Utknąłem, nie mam pomysłu, przeglądałem dokumentacje Symphony i Zenda, ciężko znaleźć coś konkretnego o front controlerze - w dokumentacji tych frameworków fc nie jest obiektem, a jeśli dobrze Was zrozumiłem fc miał być obiektem.

Ponadto utknąłem na etapie gdy kontroler wywołuje return new Response - nie mam pomysłu jak front controller ma przechwycić return new Response, skoro to dispath w ruterze wywołuje tą metodę w linijce
  1. $controller_object->$action();
Kojarzycie jakieś artykuły z rozpisanym MVC w taki sposób, że fc obsługuje response?

Tutaj mocno roboczy i tymczasowy kod:

Odwiedź moją stronę


EDIT: Coś wykminiłem, nie podpowiadajcie, niedługo wrócę smile.gif

Ten post edytował mrpickles 6.12.2019, 19:01:42
Go to the top of the page
+Quote Post
athabus
post 6.12.2019, 21:45:45
Post #27





Grupa: Zarejestrowani
Postów: 898
Pomógł: 46
Dołączył: 2.11.2005
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Najprościej chyba możesz to zrobić przechwytując we front controlerze rezultat zwrócony przez dispatcher np. tak:

Kod
(...)
    public function run()
    {
        try {
            $response = $this->dispatcher->dispatch();

            if (! $response instanceof ResponseInterface) {
                throw new \Exception('Controller must return Response object');
            }

            $response->process();

        } catch (AccessForbiddenException $e) {
            $this->handleError($e, 403);
        } catch (PageNotFoundException $e) {
            $this->handleError($e, 404);
        } catch (\Exception $e) {
            $this->handleError($e, 500);
        }
    }
(...)
Go to the top of the page
+Quote Post
mrpickles
post 8.12.2019, 20:51:37
Post #28





Grupa: Zarejestrowani
Postów: 12
Pomógł: 0
Dołączył: 14.10.2019
Skąd: Białystok

Ostrzeżenie: (0%)
-----


Zrobiłem tak, że kontroler zwraca Response, a w Ruterze w dispatch dodałem przy wywołaniu również return:
  1. return $controller_object->$action();

i obiekt response wraca do fc w linijce:a
  1. $response = $this->router->dispatch($request);


Odwiedź moją stronę wersja 1


Zrobiłem też drugie podejście, trochę przebudowując kod:
Odwiedź moją stronę wersja 2

-routeCollection zawiera tylko routing table
-do rutera wstrzykuje routecollection
-do rutera-> match() daje request, porównuje URI path z request z routing table, jak odnajduje, to wtedy zapisuje params do obiektu request
-dispatch w requestdispatcherze otrzymuje request z zapisaną poprawną scieżką w params, wywoluje po sprawdzeniu kontroler, metode
-fc otrzymuje router, request dispatcher

Pytania:
1.Czy któreś podejście jest bardziej poprawne? ( lub czy któreś jest poprawne smile.gif )
2. Czy z yaml o to chodziło, czy metoda w Core/Model jest błędna? ( działać działa )
3. Czy generując status code np. 404 mam go ustawiać poprostu w response do property statusCode, czy jednak posługiwać się http_response_code() ? Wiem, jestem niekonsekwentny w tym co wrzuciłem, ale zmienie to, jak poznam odpowiedź smile.gif
4. Napotkałem się jeszcze na sformułowanie, że Response powinien zostać zwrócony z View za pomocą ResponseFactory, a nie z Controllera. To będzie następny etap ?smile.gif

Muszę zmienić fc, ale to będzie możliwe jak wprowadze "NotAuthorizedResposne / NotFoundResponse / RedirectResponse" ale narazie nie znalazłem nigdzie nic o nich, co bym zrozumiał, stąd wrzucam co mam i będę dalej działał smile.gif



Go to the top of the page
+Quote Post

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

 



RSS Wersja Lo-Fi Aktualny czas: 16.12.2019 - 12:19