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: 36 429
Pomógł: 6289
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


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

"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ł: 48
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: 14
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ł: 48
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: 6 365
Pomógł: 1113
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: 14
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ł: 48
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: 14
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
nospor
post 7.01.2020, 16:34:45
Post #29





Grupa: Moderatorzy
Postów: 36 429
Pomógł: 6289
Dołączył: 27.12.2004




Widze nadal kodu nie testujesz wink.gif
FrontController.php

if ($response->getStatusCode() == 301) {
header('location:$file.php');
}

Po pierwsze zmienne w pojedynczych ciapkach nie sa parsowane, po drugie zmienna $file w ogole tam nie istnieje

Naucz sie uzywac === zamiast ==. Zaoszczedzi ci to kiedys sporo czasu na szukaniiu glupich bledow

return Yaml::parseFile('C:\xampp\htdocs\LibraryResponse\Core\db.yaml');
Gdy prosilismy bys wywalil konfig z gita, naprawde nie chodzilo nam bys go zastapil sciezka do pliku, do ktorego nie mamy dostepu wink.gif

public static function getDB(): object
Czemu to zwraca object? Przeciez wiesz, ze to zwraca PDO a nie byle jaki objekt

Taki kod
  1. $params = array();
  2. array_merge($params, $getParams);
  3. array_merge($params, $postParams);
  4. $this->params = $params;

Nie ma wiekszego sensu. Po mergujesz zawsze puste $params z jakas tablica? Przeciez wynikiem bedzie zawsze ta inna tablica. Co tu chcesz tak naprawde zrobic to zmergowac get i post czyli
  1. $this->params =array_merge($postParams, $getParams)



Skracaj zbedne bloki
  1. if (is_callable([$controller_object, $action])) {
  2. return $controller_object->$action();
  3. } else {
  4. throw new Exception("Method $action (in controller $controller) not found and not returned response");
  5. }


Piszesz poprostu
  1. if (is_callable([$controller_object, $action])) {
  2. return $controller_object->$action();
  3. }
  4. throw new Exception("Method $action (in controller $controller) not found and not returned response");



Cytat
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 ?

No raczej nie


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

"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
mrpickles
post 29.02.2020, 14:31:25
Post #30





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

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


Przez ostatni czas przerabiałem Laravela, teraz wróciłem do czystego PHP. Przez 2 miesiące nauki frameworka wiele rzeczy o których pisaliście stało się jasnych, więc wracam z serią pytań. Uporządkowałem gitHuba wyrzucając wszystko co stare, ponieważ i tak był tam syf, napisałem MVC od nowa.


1. Wspominaliście o obiektowym wraperze YAMLa, którego nie mogę wykminić, czy taki sposób jest ok? Wspominaliście

Plik Core/Model

  1.  
  2. public function getConfig()
  3. {
  4. return Yaml::parseFile("../Config/db.yaml");
  5. }


2. Kolejne pytanie dotyczące response/request, a dokładnie o status code 404, ale od początku:

Core/FrontController w funkcji run robi mi coś takiego:

  1.  
  2. public function run(): void
  3. {
  4. try {
  5. $request = Request::createFromGlobals();
  6. $response = $this->router->dispatch($request);
  7. $response->send();
  8. } catch (AccessForbiddenException $e) {
  9. $this->handleError($e, 403);
  10. } catch (PageNotFoundException $e) {
  11. $this->handleError($e, 404);
  12. } catch (\Exception $e) {
  13. $this->handleError($e, 500);
  14. }
  15. }


Disptach na początku wywołuje metode match().Gdy nie znajdzie ścieżki, wyrzuca "throw new PageNotFoundException('Route not found');", który złapie catch z metody run,a następnie przekaże do handleError, który ustawi status code 404 i wyświetli error. W takim wypadku jednak nie zostanie wywołana linijka z metody run $response->send(), a zgodnie z wcześniejszymi wpisami tylko ona miała wywoływać View (ustawienia/wyświetlanie headerów). Podobna sytuacja jest w przypadku drugiego wyjątku z metody Dispatch. Czy w takim przypadku response->send() powinno obsługiwać tylko status code 200, czy w nieprawidłowy sposób zrobiłem przepływ w mvc?


Odwiedź moją stronę


Go to the top of the page
+Quote Post
nospor
post 29.02.2020, 17:49:42
Post #31





Grupa: Moderatorzy
Postów: 36 429
Pomógł: 6289
Dołączył: 27.12.2004




Zrozum, rzeczy konfiguracyjne nie moga lezej w GIT. Kazdy moze miec inna konfiguracje do bazy. Wiec jak ja zmienie swoja konfiguracje do bazy to co? Mam komitowac? Ale wtedy tobie napsuje bo ty masz inna, no nie?
PLiki konfiguracyjne maja byc w .gitignore i maja nie byc zapisywane w git

W git co najwyzej mozesz zapisac sobie plik db.yml.dist ktory bedzie sluzyl jako wzor na stworzenie swojego wlasnego lokalnego pliku konfiguracyjnego. Ale to wszystko jest w znanych w FW i w laravel, ktore rzekomo uzywales


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

"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
mrpickles
post 1.03.2020, 00:11:46
Post #32





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

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


Dzięki teraz wiem o co chodzi. Tak używam laravela ale nie commitowalem go na github, jest mi zupełnie obca praca kilku osób nad projektem i stąd takie historie.
Go to the top of the page
+Quote Post

2 Stron V  < 1 2
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: 19.03.2024 - 09:47