CakePHP route redirect with parameters - redirect

I need to keep SEO links active so I'm trying to 301 redirect google trafic to new CakePHP route.
I go to:
http://localhost/jakne/someCategory/item-slug
And I want it to 301 redirect to:
http://localhost/product/item-slug
So I tried with route::redirect but I can't make it work. Doc on this is also non existent :(
$routes->redirect(
'/jakne/:subcategory/:item',
['controller' => 'Catalog', 'action' => 'product'],
['status' => 301, 'pass' => ['item']]
);
My Catalog::product looks like:
public function product($productId) {
}
I always get error that no parameter was passed to the action.
What am I missing? :(

The option for retaining parameters in redirect routes isn't pass (that's for regular routes and defines which parameters to pass as function arguments), it's persist, ie your route would need to be something like:
$routes->redirect(
'/jakne/:subcategory/:item',
['controller' => 'Catalog', 'action' => 'product'],
['status' => 301, 'persist' => ['item']]
);
This should work fine, assuming you have a proper target route connected that has a parameter named item, something like.
$routes->connect(
'/product/:item',
['controller' => 'Catalog', 'action' => 'product'],
['pass' => ['item']]
);
Generally you may want to consider doing such redirects on server level instead (for example via mod_rewrite on Apache), performance wise that's much better.
ps. Browsers do cache 301 redirects, so when making changes to such redirects, make sure that you clear the cache afterwards.
See also
Cookbook > Routing > Redirect Routing

So it turns out this is quite simple. I use this to dynamically generate a list of redirects based on what admins enter in the control panel. We use this to keep google traffic when the URL changes and is not rescanned by the google bot yet.
$builder->redirect('/from-url', '/to-url', ['status' => 301]);

Try this ways it is working for me:
Example request like: localhost:08080/get-username?id=%3Cid%3E
Routes :
$routes->connect('/get-username', ['controller' => 'Users', 'action' => 'getUserName']);
Controller :
class UsersController extends AppController {
public function initialize() {
parent::initialize();
$this->loadComponent('RequestHandler');
}
public function beforeFilter(Event $event) {
parent::beforeFilter($event);
$this->set('_serialize', false);
$this->Auth->allow([
'getUserName'
]);
}
public function getUserName() {
$id = $this->request->getQuery('id');
}
}

Related

Lumen route parameter not working with a dot

I need to find a user by email.
So i have try to route on lumen like
/user/email/abc#test.com
http://127.0.0.1:8888/user/email/abc#test.com
routes/web.php
$router->get('/user/email/{email}', ['middleware' => ['cors','auth'], 'uses' => 'UserController#getUserByEmail']);
When i have include a DOT(.) the result shows like
"The requested resource /user/email/abc#test was not found on this server."
Otherwise the result is fine.
Please advice how do i route like these scenarios or it is possible or not.
Sorry for my Bad English
I think it's a good idea to take email from request body and not from url.
In your function get the email from request. see this example:
public function getUserByEmail(Request $request){
$this->validate($request, [
'email' => 'required',
]);
$email = $request->email;
//then the rest of your code logic
}
route will be now like this:
$router->get('/user/email', ['middleware' => ['cors','auth'], 'uses' => 'UserController#getUserByEmail']);

how to make optional parametres in zendframework URL

I am new to Zend, but very very keen to learn. This is really just a quick question on routing in Zend Framework.
I understand the basic of it but I am still confused about how I can create some optional parameters at the end of my URL. For example, I have the following default page URL:
examplesite.com/accounts/enquiry
I now want to add two additional parameters to it i.e:
userid= 6
location= 12
So, the eventual URL should look like:
examplesite.com/accounts/enquiry/6/12
but
examplesite.com/accounts/enquiry
Will get you to the same page.
I am not clear. How do it do this? I mean, this is not a bespoke URL. so, I don't need to create a custom route. It basically just the last two parameters that need to be added to the page.
How do I do this?
First 2 parameters are controller and action name, the named params.
Here you are:
examplesite.com/accounts/enquiry/userid/6/location/12
or you can define your own route like this:
$route = new Zend_Controller_Router_Route('accounts/enquiry/:userid/:location);
and then add it to router:
$router->addRoute('accounts', $route);
You could add a custom route inside your Bootstrap.php, e.g. (untested):
protected function _initRoutes()
{
[...]
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$accounts = new Zend_Controller_Router_Route(
'accounts/enquiry/:userid/:location',
array(
'userid' => '[0-9]{2}',
'location' => '[0-9]{2}',
'controller' => 'accounts',
'action' => 'enquiry',
)
);
$router->addRoute('accounts', $accounts);
[...]
}
http://framework.zend.com/manual/1.12/en/zend.controller.router.html

Zend router behaviour

I have some trouble with the router.
I have a custom route :
$router->addRoute('showTopic',
new Zend_Controller_Router_Route('/forum/topic/:topic',
array('module' => 'forum',
'controller' => 'topic',
'action' => 'show'),
array('topic' => '\d+')));
But when I try to access this url : localhost/forum/topic/16
I get this error :
Fatal error: Uncaught exception 'Zend_Controller_Router_Exception' with message 'topic is not specified'
But I don't want to put a default value for topic, because I also want the route /forum/topic to list all topics...
Secondly, I know that if I add a custom route, the default router is overridden, but I need to have some default routes too. The only way I have found is to set 'default' in the second parameter of the url view helper, like this
$this->url(array(
'module' => 'forum',
'controller' => 'topic',
'action' => 'add'
), 'default', true)
Is there a more elegant way instead of doing this for all url where I want to use the default behavior ?
You should have a default value for a topic and add the more general route (the one for forum/topic) after the more specific one. Route_Rewrite checks the routes beginning with the last one (it actually does an array_inverse).
The url helper delegates assembly urls to a route, its second paremeter being the name of the route to pull from the router. Since the default route is registered under the name of 'default', there is nothing really inelegant in using the name (it is not a magic string or a special case). If this really bugs you, you could write a custom helper (to be placed under "views/helpers"):
class Zend_View_Helper_DefaultUrl extends Zend_View_Helper_Abstract {
public function defaultUrl($params) {
return $this->view->url($params, 'default');
}
}
And use it in your view like defaultUrl(array('action'=>'test')) ?>.

How to route multi subdomain with zend router hostname

I need to create routing in Zend to simply copy the current live site url structure which is sadly inconsistent
What i want to do is to route subdomain as follow:
www.site.com -> static router
a.site.com & b.site.com -> category controller
c.site.com & d.site.com -> location controller
the rest sub domain -> user controller
could anyone guide me how to solve this, thanks.
UPDATE:
First thanks Fge, vote your answer, it works but i need some more advice:
Since i have many subdomains for each rules is there a better way than add the rules in looping
foreach($subdomains as $a){
$tr = new Zend_Controller_Router_Route_Hostname(
"$a.site.com",
array(
'module' => 'mod',
'controller' => 'ctrl',
'param_1' => $a
));
$router->addRoute($a,$tr);
}
How to combine it with other routing type to parse the parameters (chained?), something like http://a.site.com/:b/:c, i want t parse it to param_1 (a), param_2 (b), param_2 (c)
Note: Reverse Matching
Routes are
matched in reverse order so make sure
your most generic routes are defined
first.
(Zend_Controller_Router)
Thus you have to define the route for all other subdomains first, then the specific ones:
$user = new Zend_Controller_Router_Route_Hostname(
':subdomain.site.com',
array(
'controller' => 'user'
)
);
$location1 = new Zend_Controller_Router_Route_Hostname(
'c.site.com',
array(
'controller' => 'location'
)
);
$location1 = new Zend_Controller_Router_Route_Hostname(
'd.site.com',
array(
'controller' => 'location'
)
);
// other definitions with known subdomain
$router->addRoute($user); // most general one added first
$router->addRoute($location1);
$router->addRoute($location2);
// add all other subdomains
Update for the updated question:
1) This really depends on how different the parameters are you want to route a subdomain to. In your example you routed them all to the same model and controller and added the actual subdomain as a parameter. This can be done easily with the user-route i posted above. There the subdomain is set as parameter subdomain ($request->getParam("subdomain")). If you want the subdomains to be the action of a known controller/model you could replace :subdomain with :action. But as soon as you have other controllers/models for each subdomain, I'm affraid you have to loop over them (or use a config file). For the example you provided in the question, the route simply could look like this:
$user = new Zend_Controller_Router_Route_Hostname(
':param1.site.com',
array(
'controller' => 'user'
)
);
// routes "subdomain".site.com to defaultModul/userController/indexAction with additional parameter param1 => subdomain.
As long as you don't have any schema in your subdomains it's very difficult to route them in a general way.
2) That's an example where router chains come into play. The outer route would be the hostname route which handles the subdomain and the inner route would handle the :a/:b part. This could look like this for example:
$user->chain(new Zend_Controller_Router_Route(':a/:b'));

Zend Framework: Need help setting up Routing

how do i set up routing as follows
these work with the standard routing
/posts => index action (listing)
/posts/view => view action (individual post)
/posts/add => add action
/posts/edit => edit action
what abt these?
/posts can by filtered based on 1 or more query strings, in any order. eg.
/posts/tagged/tag1
/posts/tagged/tag1/timeframe/1w => fyi. 1w means 1 week
/posts/timeframe/1w/tagged/tag1 => can be in any order
/posts/sortby/dtposted => more options maybe added
how can i handle these? i tried
$route = new Zend_Controller_Router_Route(
'posts/*',
array(
'controller' => 'posts',
'action' => 'index'
)
);
$router->addRoute('postsIndex', $route);
but of cos, all routes to posts/* goes to the index controller. not what i want
You dont need to use a route for those url's if your using proper naming conventions it should naturally.
class PostsController extends Zend_Controller_Action{
public function viewAction(){
}
public function editAction(){
}
public function addAction(){
}
public function indexAction(){
}
}
I suggest going back to basics and learning how controllers models and views work in the zend framework before trying to understand routing :)