问题
I have a site that needs to allow multiple URL structures. For example:
www.examplesite.com/people/add // <-- example company
www.otherexample.com/xyz/people/add // <-- "xyz" company (not location based)
www.otherexample.com/florida/abc/people/add //<-- "abc" company (location based)
Each URL should be able to detect which company it is based on the URL.
So far, I've been able to parse out the URL just fine to determine which company it is, but how to I add these extra /florida/abc/
parts to the routes to allow the rest of the app to work?
I've tried a number of things including setting a variable to the '/florida/abc' (or whatever it is) at the top of the routes file, then adding that before each route, but that doesn't handle every controller/action and seems very hit or miss/buggy.
I also use the admin
prefix, so for example, it would also need to work like this:
www.otherexample.com/admin/florida/abc/people/add
My assumption is that I need to use the routes.php
file, but I can't determine within that how I can make this happen.
回答1:
I used that approach in the web application farm.ba (not more maintained by the owner).
What I did:
- Create table "nodes" with fields id, slug, model, foreign_key, type, ..
- Create custom route (1),(2) class that handles Node model
- After save post, store and cache slug in Node Model
- After deleting the post, delete the cache and node records
This works much like wordpress routing, allows you to enter custom slug, etc.
EDIT:
Create custom route class in App/Lib/Routing/Router/MultiRoute.php like:
<?php
App::uses('CakeRoute', 'Routing/Route');
/**
* MultiRoute
*/
class MultiRoute extends CakeRoute
{
public function parse($url)
{
// debug($url); '/florida/abc/people/add'
// Add custom params
$params = array(
'location' => null,
'company' => null,
'controller' => 'peoples',
);
$params += parent::parse($url);
// debug($params);
/**
* array(
* 'location' => null,
* 'company' => null,
* 'controller' => 'peoples',
* 'named' => array(),
* 'pass' => array(
* (int) 0 => 'florida', // location
* (int) 1 => 'abc', //company
* (int) 2 => 'people', // controller
* (int) 3 => 'add' // action, default index
* ),
* 'action' => 'index',
* 'plugin' => null
* )
*
*/
// reverse passed params
$pass = array_reverse($params['pass']);
// debug($pass);
/**
* array(
* (int) 0 => 'add',
* (int) 1 => 'people',
* (int) 2 => 'abc',
* (int) 3 => 'florida'
* )
*/
if(isset($pass[3])) { $params['location'] = $pass[3]; }
if(isset($pass[2])) { $params['company'] = $pass[2]; }
// if you need load model and find by slug, etc...
return $params;
}
public function match($url)
{
// implement your code
$params = parent::match($url);
return $params;
}
}
in routes.php
App::uses('MultiRoute', 'Lib/Routing/Route');
Router::connect('/admin/*',
array('admin' => true),// we set controller name in MultiRoute class
array('routeClass' => 'MultiRoute')
);
Router::connect('/*',
array(),// we set controller name in MultiRoute class
array('routeClass' => 'MultiRoute')
);
In your controller find results using extra request params, like:
$this->request->location;
$this->request->company;
I hope this is helpful.
回答2:
Creating a route for each case seems the way to go:
Router::connect('/people/add', array('controller' => 'people', 'action' => 'add'));
Router::connect('/:company/people/add', array('controller' => 'people', 'action' => 'add'), array('pass' => array('company'), 'company' => '[a-z]+'));
Router::connect('/:location/:company/people/add', array('controller' => 'people', 'action' => 'add'), array('pass' => array('company', 'location'), 'company' => '[a-z]+', 'location' => '[a-z]+'));
Then the controller can receive these values:
public function add($company = '', $location = '') {
var_dump($company, $location); exit;
}
Mind the regex in routes and amend to match your incoming data.
来源:https://stackoverflow.com/questions/39358653/different-levels-of-url-with-cakephp-routes