URL redirection in CAKEPHP with database values - php

I am working on a project based on cakephp. I just wanted to know How can I make a perfect URL redirection form database value.
For example
I give here two current URLs and desired URLs
1.Current
/search?vendor=combo-training-certification-courses
1.Desired
combo-training-certification-courses
2.Current
/search?vendor=pmi-training-certification-courses
2.Desired
/pmi-training-certification-courses
Please tell me how can I achieve it...

Just Add following code in config/routes.php
App::uses('ClassRegistry', 'Utility');
$Route = ClassRegistry::init('Vendor'); //MODEL NAME You can change it as your needs.
$routes = $Route->find('all');
foreach ($routes as $route) {
Router::connect('/', array('controller' => $route['Route']['controller'], 'action' => $route['Route']['action']));
}
Reference

Related

CakePHP, Routing for optional controller using generic controller otherwise

I'd like to make an application in CakePHP which manages exercises and users results. Users and results are not important in this question.
I want to have a possibility to add an exercise with adding only a specific table and line to .ini config file. Application should route to a GenericExercisesController if specific one doesn't exists. Controller should load a GenericExerciseModel if specific doesn't exists. I'd managed with model loading and partially with routing with controller like this:
In route.php
foreach(Configure::read('exercisesTables') as $exerciseName){
if( App::import('Controller', Inflector::pluralize($exerciseName))){
Router::connect('/exercises/'.Inflector::pluralize($exerciseName).'/:action', array('controller' => Inflector::pluralize($exerciseName)));
}else{
Router::connect('/exercises/'.Inflector::pluralize($exerciseName).'/:action', array('controller' => 'GenericExercises', 'fakeModel' => $exerciseName));
}
}
So if I want to load an exercise Foo I should use address:
http://example.com/exercises/Foos/view
And this works fine, doesn't matter if specific controller exists.
Problem begins when I use reverse routing to generate links in views. If exercise Foo have specific controller this works correctly:
print $this->Html->url(array('controller' => Inflector::pluralize($exerciseName), 'action' => 'view'));
produces:
/exercises/Foos/view
But when exercise Bar doesn't have specific controller then the same code produces:
/Bars
This causes a problem, there is no Bars Controller.
Temporarily I'm generating those links manually, but I don't think that this is the best solution:
print $this->Html->url("/".Configure::read('exerciseRoutingPrefix')."/".Inflector::pluralize($exerciseName)."/view");
Maybe someone of you know a better solution. Thank you for reading my question.
UPDATE 1:
Those are routes in route.php defined before foreach in order as they're in file:
Router::connect('/', array('controller' => 'questions', 'action' => 'regulations'));
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
Router::connect('/help', array('controller' => 'pages', 'action' => 'faq'));
If I understood your question correctly, you could try making a "MyHtmlHelper" which does some magic before parsing your options to the HtmlHelper::link();
You can do it like so:
/app/View/Helpes/MyHtmlHelper.php
Create a helper which extends the "HtmlHelper" like so:
<?php
App::uses('HtmlHelper', 'View/Helper');
class MyHtmlHelper extends HtmlHelper {
public function link($title, $url = null, $options = array(), $confirmMessage = false) {
//do your magic here and change the $title, $url or $options accordingly.
return parent::link($title, $url, $options, $confirmMessage);
}
}
Now in your controller, you should include the Helper like so (aliasing) $helpers = array('Html' => array('className' => 'MyHtml')); instead of $helpers = array('Html');.
I guess you can fill in the blanks on the public function link yourself. If not, feel free to ask more help :)
More about helpers
Off course it is possible to do this with every other Helper or method you can think off. HtmlHelper::link() is just used as example.

CakePHP: Redirect in routes.php

OK, I dont know if I am taking the wrong approach or not but am stuck here...
We have developed our website and we have many controllers expecting ids and special variables, links already redirecting to the controllers passing what is expected.
The new requirement is to use friendlyUrls and the idea is that instead of having:
http://domain.com/search/advanced/term:head/city:/set:show-all/sort:basic-relevance
it now reads
http://domain.com/search/head
or passing options.
http://domain.com/search/in-edinburgh-scotland/by-rating/head
My idea was to, at the beginning of the Routes.php have a simple if such as:
$friendlyUrl = $_SERVER['REQUEST_URI'];
$friendlyUrl = split('/', $friendlyUrl);
foreach ($friendlyUrl as $key => $params) {
if(empty($params)){
unset($friendlyUrl[$key]);
}
if($params == 'search'){
Router::connect('/search/*', array('plugin'=>'Search','controller' => 'Search', 'action' => 'advancedSearch', 'term'=>'head));
}elseif ($params == 'employers') {
# code...
}elseif ($params == 'employer-reviews') {
# code...
}elseif ($params == 'jobs') {
# code...
}
}
That didn't work, then I tried adding something similar in my AppController and nothing.
All in all the the thing that has to do is:
Url be in the format of: /search/{term}
Actually be redirecting to: /search/advanced/{term}/city:{optional}/set:show-all/sort:basic-relevance
URL bar to keep reading: /search/{term}
Anyone has an idea?! Thank you
You definitely want to have a look at the routing page in the book
http://book.cakephp.org/2.0/en/development/routing.html
There are tons of options there to match url patterns to pass parameters to the controllers.
Router::connect(
'/search/:term',
array('controller' => 'search', 'action' => 'advanced'),
array(
'pass' => array( 'term')
)
);
You should probably set the defaults for city & set & sort in the actions function parameters definitions:
public function advanced($term, $city='optional', $sort = 'basic'){
// your codes
}
The great thing about doing it this way, is that your $this->Html->link's will reflect the routes in the paths they generate. (reverse routing)
The routes in cake are quite powerful, you should be able to get some decent friendly urls with them. One extra thing I've used is to use a behaviour - sluggable - to generate a searchable field from the content items title - for pages / content types in the cms.
good luck!

Append param to current URL with view helper in Zend

In my layout-script I wish to create a link, appending [?|&]lang=en to the current url, using the url view helper. So, I want this to happen:
http://localhost/user/edit/1 => http://localhost/user/edit/1?lang=en
http://localhost/index?page=2 => http://localhost/index?page=2&lang=en
I have tried the solution suggested Zend Framework: Append query strings to current page url, accessing the router directly, but that does work.
My layout-script contains:
English
If the default route is used, it will append /lang/en, but when another route is used, nothing is appended at all.
So, is there any way to do this with in Zend without me having to parse the url?
Edit
Sorry for my faulty explanation. No, I haven't made a custom router. I have just added other routes. My bad. One route that doesn't work is:
$Routes = array(
'user' => array(
'route' => 'admin/user/:mode/:id',
'defaults' => array('controller' => 'admin', 'action' => 'user', 'mode'=>'', 'id' => 0)
)
);
foreach( $Routes as $k=>$v ) {
$route = new Zend_Controller_Router_Route($v['route'], $v['defaults']);
$router->addRoute($k, $route);
}
Upd:
You must add wildcard to your route or define 'lang' parameter explicitly.
'admin/user/:mode/:id/*'
Additionally, according to your comment, you can do something like this:
class controllerplugin extends Zend_Controller_Plugin_Abstract
{
function routeShutdown($request)
{
if($request->getParam('lang', false) {
//store lang
Zend_Controller_Front::getInstance()->getRouter()->setGlobalParam('lang', NULL); //check if this will remove lang from wildcard parameters, have no working zf installation here to check.
}
}
}

CakePHP Routing help

I want to make my /pages/about become just `/about
I tried doing it with the routing in routes.php but couldn't get it working e.g. Router::connect('/pages/about', array('controller' => 'pages', 'action' => 'display'));
can anyone help?
ALSO
for my portfolio controller I have it currently showing work like /portfolio/view/102 but I would like to display it something like /portfolio/view/Paperview_Magazine-102 where Paperview Magazine is the title of the post and 102 is the ID of the post. I have looked at the Cake Book but if someone could post up some code that'd be awesome.
Thanks
To make a route for /about, you need to make a route for /about, not /pages/about:
Router::connect('/about',
array('controller' => 'pages', 'action' => 'display', 'about'));
To use URLs like /portfolio/view/Paperview_Magazine-102, you can use standard routes, but you'll have to do a little work in the controller:
// PortfolioController
// $identifier == "Paperview_Magazine-102"
public function view($identifier) {
if (!preg_match('/^(.+)-(\d+)$/', $identifier, $matches)) {
// $identifier is not in format 'Title-Id'
$this->cakeError('error404');
}
// $matches[1] == Paperview_Magazine
// $matches[2] == 102
$post = $this->Portfolio->read(null, $matches[2]);
$this->set(compact('post'));
}
Maybe a bit of a long shot, but in the first one you could try Router::connect('/:controller/about', array('action'=>'display'));? I seem to remember having some similar problems with my routes and this maybe helping, though I can't remember why.
With the second question, can't you just rework the view function so it accepts a $slug parameter instead of $id, and find the right portfolio record by searching on the slug instead? Or check if the parameter is_numeric, and search for an id if it is, or a slug if it isn't...

change CakePhp1.3 paginator destination url?

I'm new to cakephp...and I have a page with a url this:
http://localhost/books/filteredByAuthor/John-Doe
so the controller is ´books´, the action is ´filteredByAuthor´ and ´John-Doe´ is a parameter.. but the url looks ugly so i've added a Route like this:
Router::connect('/author/:name', array( 'controller' => 'books','action' => 'filteredByAuthor'), array('pass'=>array('name'),'name'=>".*"));
and now my link is:
http://localhost/author/John-Doe
the problem is that the view has a paginator and when i change the page (by clicking on the next or prev button).. the paginator won't consider my routing... and will change the url to this
http://localhost/books/filteredByAuthor/John-Doe/page:2
the code on my view is just:
<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
the documentation doesn't say anything about avoiding this and i've spent hours reading the paginators source code and api.. and in the end i just want my links to be something like this: (with the sort and direction included on the url)
http://localhost/author/John-Doe/1/name/asc
Is it possible to do that and how?
hate to answer my own question... but this might save some time to another developper =) (is all about getting good karma)
i found out that you can pass an "options" array to the paginator, and inside that array you can specify the url (an array of: controller, action and parameters) that the paginator will use to create the links.. so you have to write all the possible routes in the routes.php file. Basically there are 3 possibilities:
when the "page" is not defined
For example:
http://localhost/author/John-Doe
the paginator will assume that the it's the first page. The corresponding route would be:
Router::connect('/author/:name', array( 'controller' => 'books','action' => 'filteredByAuthor'),array('pass'=>array('name'),'name'=>'[a-zA-Z\-]+'));
when the "page" is defined
For example:
http://localhost/author/John-Doe/3 (page 3)
The route would be:
Router::connect('/author/:name/:page', array( 'controller' => 'books','action' => 'filteredByAuthor'),array('pass'=>array('name','page'),'name'=>'[a-zA-Z\-]+','page'=>'[0-9]+'));
finally when the page and the sort is defined on the url (by clicking on the sort links created by the paginator).
For example:
http://localhost/author/John-Doe/3/title/desc (John Doe's books ordered desc by title)
The route is:
Router::connect('/author/:name/:page/:sort/:direction', array( 'controller' => 'books','action' => 'filteredByAuthor'),
array('pass'=>array('name','page','sort','direction'),
'name'=>"[a-zA-Z\-]+",
'page'=>'[0-9]*',
'sort'=>'[a-zA-Z\.]+',
'direction'=>'[a-z]+',
));
on the view you have to unset the url created by the paginator, cause you'll specify your own url array on the controller:
Controller:
function filteredByAuthor($name = null,$page = null , $sort = null , $direction = null){
$option_url = array('controller'=>'books','action'=>'filteredByAuthor','name'=>$name);
if($sort){
$this->passedArgs['sort'] = $sort;
$options_url['sort'] = $sort;
}
if($direction){
$this->passedArgs['direction'] = $direction;
$options_url['direction'] = $direction;
}
Send the variable $options_url to the view using set()... so in the view you'll need to do this:
View:
unset($this->Paginator->options['url']);
echo $this->Paginator->prev(__('« Précédente', true), array('url'=>$options_url), null, array('class'=>'disabled'));
echo $this->Paginator->numbers(array('separator'=>'','url'=>$options_url));
echo $this->Paginator->next(__('Suivante »', true), array('url'=>$options_url), null, array('class' => 'disabled'));
Now, on the sort links you'll need to unset the variables 'sort' and 'direction'. We already used them to create the links on the paginator, but if we dont delete them, then the sort() function will use them... and we wont be able to sort =)
$options_sort = $options_url;
unset($options_sort['direction']);
unset($options_sort['sort']);
echo $this->Paginator->sort('Produit <span> </span>', 'title',array('escape'=>false,'url'=>$options_sort));
hope this helps =)

Categories