Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

2 Stron V   1 2 >  
Reply to this topicStart new topic
> [inny][Laravel5] Pełny routing na sluggach z bazy danych
dado
post
Post #1





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


Laravel 5.1

Nadziobałem własny routing pozwalający na użycie pełnych slugów: adres strona.pl/to-jest-jakis-tam-slug wywołuje odpwiadający slugowi kontroler akcji parametry. efekty uzyskałem poprzez middleware-a. Wszystko działa fajnie ale jest jeden poważny problem. Jeśli nie ma zdefiniowanego routingu w bazie uzyte w middleware return $next($request); nie powoduje szukania w innych regułach routingu (np cześć administracyjna w ścieżce /admin ) tylko wyświetla pustą stronę.
Czy wiecie może jak można poradzić sobie z tym problemem? Np czy jest jakiś parametr dający możliwość dodania wykluczeń do danej reguły routingu? Ktoś? Coś?

Plik middlewarea:
  1. <?php
  2.  
  3. namespace App\Modules\Front\Http\Middleware;
  4.  
  5. use App;
  6. use Closure;
  7. use Route;
  8. use App\Modules\Front\Models\SluggableModel;
  9.  
  10. class FrontendSlugRoute
  11. {
  12.  
  13. /**
  14.   * Handle an incoming request.
  15.   *
  16.   * @param \Illuminate\Http\Request $request
  17.   * @param \Closure $next
  18.   * @internal param $slug
  19.   * @return mixed
  20.   */
  21. public function handle($request, Closure $next)
  22. {
  23. if(isset($request->slug) && !empty($request->slug)){
  24. if($slug = SluggableModel::where('slug', $request->slug)->first()){
  25.  
  26. App::call([app($slug->controller), $slug->action], $slug->params);
  27. }
  28. else{
  29. return $next($request);
  30. }
  31. }
  32. else{
  33. return $next($request);
  34. }
  35. }
  36. }


zawartość pliku route.php dla tego routingu
  1. Route::get('/{slug}', ['as' => 'sluggable', 'middleware' => 'sluggable', function () {
  2.  
  3. }])->where('slug', '.*');


Ten post edytował dado 5.01.2016, 14:43:15
Go to the top of the page
+Quote Post
Pyton_000
post
Post #2





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Hmm.. Nie za bardzo rozumiem a co chodzi ale może zamiast Twojego rozwiązanie to będzie pasowało: https://blog.piotrows.pl/laravel-5-global-routing-package/
Go to the top of the page
+Quote Post
dado
post
Post #3





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


Widziałem już tą paczkę. Niestety nie pozwala ona na pełne slugi. Mi chodzi aby slug nie zawierał nazw kontrolerów, akcji czy nawet id.
Chodzi o to że tak skontruowany przezemnie routing w przypadku braku odpowiednika w bazie nie zadziała - jasno to widać tutaj:
  1. Route::get('/{slug}', ['as' => 'sluggable', 'middleware' => 'sluggable', function () {
  2. // tutaj nie ma żadnych reguł bo wszystko się dzieje w middlewarach ale jak nie ma nic w bazie to też nic się nie wywoła
  3. }])->where('slug', '.*');
  4.  
  5. //inne routing które nie są wywoływane
  6. // Authentication routes...
  7. Route::get('auth/login', 'Auth\AuthController@getLogin');
  8. Route::post('auth/login', 'Auth\AuthController@postLogin');
  9. Route::get('auth/logout', 'Auth\AuthController@getLogout');
  10.  
  11. // Registration routes...
  12. Route::get('auth/register', 'Auth\AuthController@getRegister');
  13. Route::post('auth/register', 'Auth\AuthController@postRegister');
  14.  


Ten post edytował dado 5.01.2016, 15:03:21
Go to the top of the page
+Quote Post
Pyton_000
post
Post #4





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Bo to ma być ostatni routing który łapie wszystko co nie zostanie znalezione w statycznym. Wstaw globalny na sam koniec a stanie się światłość smile.gif

PS. Dałeś fajny pomysł na rozbudowę mojej paczki smile.gif

Ten post edytował Pyton_000 5.01.2016, 15:09:15
Go to the top of the page
+Quote Post
dado
post
Post #5





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


Racja to rzeczywiście załatwiało by sprawę gdyby plik route.php bł jeden. Niestety apka podzielona jest na moduły z własnymi plikami route.php i w konsoli nawet jak pokazuje się jako ostatni:
Cytat
| | POST | auth/login | | App\Modules\Admin\Http\Controllers\Auth\AuthController@postLogin | guest |
| | GET|HEAD | auth/login | | App\Modules\Admin\Http\Controllers\Auth\AuthController@getLogin | guest |
| | GET|HEAD | auth/logout | | App\Modules\Admin\Http\Controllers\Auth\AuthController@getLogout | |
| | POST | auth/register | | App\Modules\Admin\Http\Controllers\Auth\AuthController@postRegister | guest |
| | GET|HEAD | auth/register | | App\Modules\Admin\Http\Controllers\Auth\AuthController@getRegister | guest |
| | GET|HEAD | {slug} | sluggable | Closure | sluggable


to i tak łapię się jako pierwszy. Nie wiem czemu.

Ps. Spoczko. Rób upgrade wink.gif zapnę do vendorów smile.gif
Go to the top of the page
+Quote Post
Pyton_000
post
Post #6





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Jeśli robisz route:list to ta lista wynikowa jest właśnie w takiej kolejności parsowana.

Go to the top of the page
+Quote Post
dado
post
Post #7





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


No niestety nie działa tak jak piszesz. Owszem załapują się routingi napisane powyżej slug routingu w ramach jednego pliku routes.php. Ale gdy wprowadzam adres do innego modułu to załapuje się na routing z slugiem. Do modułowości w L5 używam https://github.com/caffeinated/modules.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #8





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Ok.

W takim razie w config/app.php znajdź:

Kod
Illuminate\Routing\ControllerServiceProvider::class

i przenieś przed ten wpis ServiceProivder z Modules.

Wtedy niema bata, musi zadziałać.

PS. Jesli wywali błedy to przenieś oba wpisy niżej pod
Kod
Illuminate\View\ViewServiceProvider::class,
Go to the top of the page
+Quote Post
dado
post
Post #9





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


Hej, też nie działa niestety. W middleware wylistowałem sobie wszystkie zarejestrowane routingi i slug jest jako pierwszy. Jest jakiś patent żeby przenieść go na sam dół?
Cytat
RouteCollection {#26 ▼
#routes: array:6 [▶]
#allRoutes: array:34 [▼
"HEAD{slug}" => Route {#140 ▶}
"HEAD_debugbar/open" => Route {#142 ▶}
"HEAD_debugbar/clockwork/{id}" => Route {#143 ▶}
"HEAD_debugbar/assets/stylesheets" => Route {#144 ▶}
"HEAD_debugbar/assets/javascript" => Route {#145 ▶}
"HEADnews" => Route {#233 ▶}
"HEADmenu" => Route {#241 ▶}
"HEADmaps" => Route {#230 ▶}
"HEADadmin/pages" => Route {#247 ▶}
"HEADadmin/pages/create" => Route {#246 ▶}
Go to the top of the page
+Quote Post
Pyton_000
post
Post #10





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Aaaaa dobra... Mój błąd. Nie zauważyłem że tego sluga dajesz w Module.
To będzie wyzwanie smile.gif

Możesz ew. zadeklarować tego Slug w main routes.php (ale wcześniejsza zmiana w ServiceProvider ad kolejności dołączania musi być zaaplikowana)

Ew. w ServiceProvider dla Modułu albo w register albo w boot (nie pamiętam które się odpala jako ostatnie).
Go to the top of the page
+Quote Post
dado
post
Post #11





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


Zrobiłem tak jak pisałeś i niestety routing jest nieco dalej ale nie jest ostatni. Znalazłem następujący sposób. W Exceptions/Handler w miejscu gdzie wykrywany jest 404 odpalam midllewara sprawdzającego slugi. Niby działa ale rozwiązanie trochę partyzanckie. Grzebałem na githubie i wszystkie routingi na slugach oparte są o patern np post/{slug}, page/{slug} itd... Może w L5 nie da się zrobić routingu na pełnym slugu?
Go to the top of the page
+Quote Post
phpion
post
Post #12





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Wprawdzie z Laravelem styczności nie miałem, ale swego czasu robiłem tak w Kohanie. Nie można po prostu po odebraniu sluga z URLa sprawdzić czy dany moduł/kontroler/akcja istnieje? Jeśli nie to dopiero wtedy zasysać dane z bazy. Czyli dla sluga auth/login sprawdzamy czy istnieje odpowiednia akcja. Istnieje więc nie robimy nic tylko puszczamy żądanie dalej. Dla sluga jakas-strona nie ma takiej akcji w naszych plikach więc szukamy wpisu w bazie.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #13





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Da się zrobić. ale z racji tego że używasz tego Slug w Module to pliki routingu sa ładowane po kolei (Wpierw z globalnego routes.php potem z Modeli pewnie wg jakiegoś tam schematu).

Wynika to z kolejności wczytywania.

Możesz albo zostawić tak jak masz albo ustawić ServiceProvider tak aby globalny routes.php wczytywał sie ostatni (po ModulesServiceProvider) i tam na koniec wpakować tego Slug. Oczywiście okraszając go odpowiednim namespace.

@phpion tutaj to nie zadziała, bo url pasuje do patternu Slug więc go wykonuje. nie przejdziesz dalej. Trzeba by było poszukać czy da się oszukać tak aby właśnie puścił po braku w bazie. Wtedy miejsce deklaracji mogłoby być dowolne.

Ten post edytował Pyton_000 7.01.2016, 13:11:48
Go to the top of the page
+Quote Post
phpion
post
Post #14





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Ok, niech sobie pasuje do wzorca *. Ja ten warunek wrzuciłbym do FrontendSlugRoute::handle() na zasadzie:

  1. public function handle($request, Closure $next)
  2. {
  3. if(isset($request->slug) && !empty($request->slug)){
  4. $controller = substr...
  5. $action = substr...
  6.  
  7. if($this->acitonExists($controller, $action) === FALSE && $slug = SluggableModel::where('slug', $request->slug)->first()){
  8.  
  9. App::call([app($slug->controller), $slug->action], $slug->params);
  10. }
  11. else{
  12. return $next($request);
  13. }
  14. }
  15. else{
  16. return $next($request);
  17. }
  18. }

Minus tego byłby jednak taki, że cały routing musiałby być w bazie danych. Chyba, że Laravel umożliwia również sprawdzenie czy dany slug pasuje do już zdefiniowanej (w plikach) trasy.

* możliwe, że nie rozumiem przepływu w Laravelu. Przy swoich wywodach zakładam, że całe to middleware to taki hook z Kohany, czyli wykonuje się niezależnie od całego przepływu i może na niego wpłynąć, ale nie musi.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #15





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


Tak, middleware jest takim filtrem.

Jednak odpala się dopiero jeśli core znajdzie dopasowanie w route, wtedy dopiero odpala middleware. I tam możesz wpływać na Request, i albo puszczasz dalej abo blokujesz.
Jeśli nastąpiło dopasowanie do route to nie będzie dalej sprawdzane pozostałe.

Dlatego tak istotna jest kolejnośc wpisów w route.
Go to the top of the page
+Quote Post
phpion
post
Post #16





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Zgadza się, ale jeśli założymy, że cały routing slugów będzie w bazie danych to możemy mieć tylko 1 wpis tras w konfiguracji kierujący wszystko do wspomnianej metody handle(). W niej sprawdzamy to co opisałem wcześniej. I tak jak napisałem minus jest taki, że nie możemy mieć innych wpisów w konfiguracji routingu, każdy request musi iść przez nasze middleware.
Go to the top of the page
+Quote Post
memory
post
Post #17





Grupa: Zarejestrowani
Postów: 616
Pomógł: 84
Dołączył: 29.11.2006
Skąd: bełchatów

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


Nie łatwiej zrobić moduł z tym routingiem i dodać go jako ostatni ?. W Manifest File wystarczy ustawić order:999999.
- ładowany jest global routing
- ładowane routingi modułów według order
Go to the top of the page
+Quote Post
dado
post
Post #18





Grupa: Zarejestrowani
Postów: 194
Pomógł: 2
Dołączył: 12.04.2004
Skąd: Częstochowa

Ostrzeżenie: (10%)
X----


Najprościej byłoby po order z manifestu. Sprawdzałem i wczytuje się w cały świat a nie po order. Zgłosiłem ten fakt właścicielowi paki na GH.

Próbowałem też karkołomnie odpalić Closure $next w ciele reguły route ale też nie daje rady
  1. Route::get('/{slug}', ['as' => 'sluggable', 'middleware' => 'sluggable', function (Request $request, Closure $next) {
  2. return $next($request);
  3. }])->where('slug', '[A-Za-z-0-9_\-]+');


@phpion - routing po stronie publicznej będzie po slugach ale backend już normalnie.

Ten post edytował dado 7.01.2016, 14:44:53
Go to the top of the page
+Quote Post
phpion
post
Post #19





Grupa: Moderatorzy
Postów: 6 072
Pomógł: 861
Dołączył: 10.12.2003
Skąd: Dąbrowa Górnicza




Cytat(dado @ 7.01.2016, 14:40:05 ) *
@phpion - routing po stronie publicznej będzie po slugach ale backend już normalnie.

...no i wówczas warunek:
  1. $this->acitonExists($controller, $action)

zostanie spełniony. Ok, co miałem powiedzieć powiedziałem smile.gif Laravela nie znam, a porady piszę na podstawie ogólnych przemyśleń zastosowany przeze mnie w Kohanie.
Go to the top of the page
+Quote Post
Pyton_000
post
Post #20





Grupa: Zarejestrowani
Postów: 8 068
Pomógł: 1414
Dołączył: 26.10.2005

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


@dado jeśli faktycznie jest tam coś takiego jak order i to miałoby ładować moduły wg. kolejności to w sumie załatwiło by sprawę całkowicie.
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 Aktualny czas: 19.08.2025 - 02:32