2017-05-19 64 views
8

Korzystanie CakePHP v3.3.16Definiowanie CakePHP Route wywołać określony kontroler, czy dane działanie nie istnieje

Chcę napisać trasy zastępczej w taki sposób, że jeśli URL nie jest podłączony do jakiegokolwiek działania następnie go powinien przejść do tej rezerwy.

Utworzony trasy dla SEO friendly URL jak ten

$routes->connect(
     ':slug', 
     ['prefix'=>'website','controller' => 'Brands', 'action' => 'index'], 
     ['routeClass' => 'DashedRoute'] 
    ); 
    $routes->connect(
     ':slug/*', 
     ['prefix'=>'website','controller' => 'Products', 'action' => 'index'], 
     ['routeClass' => 'DashedRoute'] 
    ); 

ale również inclute wszystkie działania kontrolera w niej więc jeśli próbuję połączyć się z kontrolera ex: Koszyk/indeks to będzie www/marki/index/index

Jeśli muszę usunąć je wykluczyć, muszę utworzyć trasę tak/

$routes->connect('/cart',['controller' => 'Cart'], ['routeClass' => 'DashedRoute']); 

I tak do drugiego kontrolera, aby uzyskać dostęp.

Przykład: Mam kontroler CartController działanie addCart

CASE 1

jeśli mam dostępu URL my_project/cart/addCart/ Należy przejść do kontrolera koszyka działania

CASE 2

jeśli mam dostępu URL my_project/abc/xyz/ i nie ma kontroler o nazwie abc więc powinien iść do BrandsController działania indeksu

Moja Aktualny routes.php wygląda to

Router::defaultRouteClass(DashedRoute::class); 

Router::scope('/', function (RouteBuilder $routes) { 

    $routes->connect('/', ['prefix'=>'website','controller' => 'Home', 'action' => 'index']); 
    $routes->connect('/trending-brands', ['prefix'=>'website','controller' => 'Brands', 'action' => 'trending']); 
    $routes->connect('/users/:action/*',['prefix'=>'website','controller' => 'Users'], ['routeClass' => 'DashedRoute']); 

    $routes->connect('/cart',['prefix'=>'website','controller' => 'Cart'], ['routeClass' => 'DashedRoute']); 
    $routes->connect('/cart/:action/*',['prefix'=>'website','controller' => 'Cart'], ['routeClass' => 'DashedRoute']); 

    $routes->connect(
     ':slug', 
     ['prefix'=>'website','controller' => 'Brands', 'action' => 'index'], 
     ['routeClass' => 'DashedRoute'] 
    ); 
    $routes->connect(
     ':slug/*', 
     ['prefix'=>'website','controller' => 'Products', 'action' => 'index'], 
     ['routeClass' => 'DashedRoute'] 
    ); 
    $routes->connect(':controller', ['prefix'=>'website'], ['routeClass' => 'DashedRoute']); 
    $routes->connect(':controller/:action/*', ['prefix'=>'website'], ['routeClass' => 'DashedRoute']); 


    $routes->fallbacks(DashedRoute::class); 
}); 

Router::prefix('website', function (RouteBuilder $routes) { 
    $routes->fallbacks(DashedRoute::class); 
}); 


Plugin::routes(); 
+0

Naprawdę powinieneś wysyłać nieprawidłowe adresy URL do strony 404. – delboy1978uk

+0

Czy możesz zadać pytanie? Masz na myśli, czy domain.comcart/jakiekolwiek działanie przejdzie do kontrolera koszyka, czy inaczej przejdzie do kontrolera brans? –

+0

Tak, ale jeśli istnieje kontroler koszyka. Np .: JEŚLI trafimy na domain.com/cart/nie i kontroler koszyka nie istnieje, to przejdzie do marek, inaczej przejdzie do kontrolera marek, gdzie koszyk jest traktowany jako ślimak –

Odpowiedz

1

If Muszę go wykluczyć, muszę utworzyć trasę taką jak ta/I tak do drugiego kontrolera, aby uzyskać dostęp do.

Nie trzeba określać każdego kontrolera/nazwy we wzorcu, zamiast tego można najpierw utworzyć wszystkie określone trasy, a następnie umieścić poniższą trasę poniżej, aby uchwycić wszystkie niedopasowane trasy.

$routes->connect(':/prefix/:controller/:action/*', [], ['routeClass' => 'DashedRoute']); 

I może jeszcze jeden bez prefiksu

$routes->connect('/:controller/:action/*', [], ['routeClass' => 'DashedRoute']); 

A skoro wspomniałeś, że używasz 3.3.* wersję ciasto, Twoje drogi mogą być napisane przy advatage z trasach scoping

Router::prefix('website', function ($routes) { 
// All routes here will be prefixed with `/prefix` 
// And have the prefix => website route element added. 
$routes->fallbacks(DashedRoute::class); 
    $routes->connect(
    '/:slug', 
    ['controller' => 'Brands', 'action' => 'index'] 
); 
$routes->connect(
    ':slug/*', 
    ['controller' => 'Products', 'action' => 'index'] 
}); 
+0

próbował nie działać, ponieważ mój adres URL pasuje do pierwszej reguły nie pójść do innych. –

+0

Ile kontrolerów trasujesz? –

+0

4 lub 5, ale chcę uogólnić, ponieważ może się rozwijać zgodnie z wymogiem. –

3

Twoje zmiany całkowicie unieważniają moją pierwszą odpowiedź, więc zdecydowałem się opublikować kolejną odpowiedź.

Nie można tego zrobić przez router, ponieważ router nie może ustalić, czy kontroler/akcja istnieje dla konkretnej trasy. Dzieje się tak dlatego, że router działa tylko z szablonami adresów URL i deleguje zadanie ładowania kontrolerów do stosu żądań.

można naśladować tę funkcję mimo że za pomocą sprawdzić, czy atrybut żądania params jest ustawiony, a następnie zatwierdź Middleware je odpowiednio i zmieniając je do kontrolera awaryjnej, jeśli kontroler docelowy nie istnieje.

Po prostu upewnij się, że wykonasz wykonanie RoutingMiddleware przed oprogramowaniem pośredniczącym, w przeciwnym razie nie będziesz mieć żadnych parametrów do sprawdzenia, ponieważ trasy nie zostałyby przeanalizowane.

Middlewares wdrażają jedną metodę __invoke().

use Psr\Http\Message\ResponseInterface; 
use Psr\Http\Message\ServerRequestInterface; 
use Cake\Http\ControllerFactory; 
use Cake\Routing\Exception\MissingControllerException; 

class _404Middleware { 

public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next) 
{ 
     //$params = (array)$request->getAttribute('params', []); 

     try { 
      $factory = new ControllerFactory(); 
      $controller = $factory->create($request, $respond); 
     } 
    catch (\Cake\Routing\Exception\MissingControllerException $e) { 
     // here you fallback to your controllers/action or issue app level redirect 
     $request = $request->withAttribute('params',['controller' =>'brands','action' => 'index']); 
     } 
    return $next($request, $response); 
} 

} 

Następnie dołączyć w swój App\Application zobaczyć również attaching middlewares

$middlewareStack->add(new _404Middleware()); 

proszę remmber aby oczyścić kod jak nie przetestować go pod prawdziwym dev't środowisku.

Po przemyśleniu: jeśli szukasz strony z błędami dla wszystkich nieodnalezionych zasobów, nie potrzebujesz tego wszystkiego, zamiast tego po prostu dostosujesz szablon błędów pod numerem Template/Error/error404.ctp.

+0

Czy możesz podać również przykład? Będzie bardziej odpowiednie –