I have the following code in my PortfolioController:
function index()
{
$this->set('posts', $this->Portfolio->find('all'));
}
function view ( $id, $slug )
{
$post = $this->Portfolio->read(null, Tiny::reverseTiny($id));
$this->set(compact('post'));
}
However in order to get the view to remove /view/ from the URL, I have added the following to my routes: Router::connect('/portfolio/*', array('controller' => 'portfolio', 'action' => 'view'));
This breaks the index method as it overrides it by calling the view method instead and shows a blank view
How do I fix this?
What are you trying to do exactly? (And what's with $slug?)
It sounds like what you want to do is remove the action (or at least the view() action?) from displaying in the URL, amirite? Kind of like the default pages_controller display() method - catch-all action for static pages?
How do I fix this?
Well, I'd suggest starting with un-breaking that route, because otherwise it's doing exactly what you told it to:
Router::connect('/portfolio/*',
// * is a wildcard matching anything & everything after /portfolio/
array('controller' => 'portfolio',
// and routing to portfolio's view() action, with or w/o required $args to pass
'action' => 'view'));
so what you see when you call index() is not a blank view, it's a suppressed fatal error, which is what happens when index() reroutes to view() and doesn't have an $id to pass in for the first arg.
Note the ending DS. Route order matters; first rule that catches, wins. The following routes would all map to index by default if the url's action were omitted, but they're not the same.
// Targets inside the controller (its methods)
Router::connect('/portfolio/',
array('controller' => 'portfolio', 'action' => 'index'));
is not the same as
// Targets the controller
Router::connect('/portfolio',
// Specifies the default controller action, can be whatever
array('controller' => 'portfolio', 'action' => 'index'));
For what you're trying to do, it should be
// Targets the controller
Router::connect('/portfolio',
// Routes to 'controller default method' which is index() by Cake default
array('controller' => 'portfolio');
This allows Cake to enforce auto default mapping to the controller's index() whenever the action is missing from the URL.
It would still have worked except for the trailing DS and trailing asterisk. The same rule that should catch index() reroutes to view() instead, thanks to the trailing asterisk targeting all actions in portfolio.
Hence Foo's suggestion doesn't work -> trailing DS + wildcard:
Router::connect('/portfolio/',
// the trailing DS changes it to target 'inside portfolio' instead of 'portfolio'
array('controller'=>'portfolio', 'action'=>'index'));
// trailing arbitrary wildcard maps any / all actions directly to view() method
Router::connect('/portfolio/*',
array('controller' => 'portfolio', 'action' => 'view'));
Which just ensures ALL actions in portfolio map directly to portfolio view() method (including /portfolio/index action). Do not pass go, etc. Any portfolio action resolves to the wildcard no matter what, aliasing the whole controller to that method. So you could knock the DS off the first route but any url starting with /portfolio that isn't /portfolio would still route to view(). Including the url /portfolio/index.
Try this:
// catches portfolio/index() without index in the url
Router::connect('/portfolio',
array('controller' => 'portfolio'));
// maps to portfolio/view() without view in url, just /portfolio/integer id
Router::connect('/portfolio/:id',
array('action'=>'view', array('id' => '[0-9]+'));
// routes everything else in portfolio as usual
Router::connect('/portfolio/:action/*',
array('controller'=>'portfolio'));
Routes can be tricky. Here are some links; HTH. :)
http://bakery.cakephp.org/articles/Frank/2009/11/02/cakephp-s-routing-explained
http://book.cakephp.org/view/46/Routes-Configuration
I'm new to CakePHP myself, but I believe you can add
Router::connect('/portfolio/', array('controller' => 'portfolio', 'action' => 'index'));
Before the route with the star.
as per my knowledge is concern
you should give like this:
Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display'));
I mean you should changes the aliases of the controller name.
Router::connect('/portfolios/*', array('controller' => 'portfolios', 'action' => 'view'));
Related
I would like to know how to route the following scenario: I have a controller called Users, in this controller I have many actions, one of those is "profile".
I want my address being like that: mysite.com/users/NameOfTheUser OR mysite.com/users/edit-profile OR mysite.com/users/edit-photo, etc.
When you go for "edit-profile" you will be redirected to the edit_profile action, but here goes the trick, when you go to "NameOfTheUser" I want to redirect to the "profile" action, passing "NameOfTheUser" as a parameter.
Is there a way to do so without routing every action manually?
EDIT
I used the code that Yosi Azwan said, it works but I have to create a new route for each other page in the controller users.
Router::connect( '/users/:name', ['controller' => 'Users', 'action' => 'profile'], ['pass' => ['name']] );
Maybe this is what you are looking for
Router::connect( '/users/:name', ['controller' => 'Users', 'action' => 'profile'], ['pass' => ['name']] );
and read this for complete documentations http://book.cakephp.org/3.0/en/development/routing.html
In my project I have some pages defined in my index controller, like ie. the About us page. In order for me not to have to type domain.com/index/about but domain.com/about I have this route:
$route = new Zend_Controller_Router_Route_Static ( 'about', array (
'controller' => 'Index',
'action' => 'about'
) );
$router->addRoute ( 'about', $route );
It does the job. The problem is that sometimes I have 6 or 7 pages and I have to repeat this route 6 or 7 times. Is there a way for me to do a route that would always remove "index" from the url? I would never need a url that has index in it. Thanks!
You can write dynamic routes by avoiding the static route type:
$route = new Zend_Controller_Router_Route(
'/:action',
array (
'controller' => 'index',
'action' => 'index',
)
);
$router->addRoute('pages', $route);
This will add a route called 'pages' that will match any single action in the index controller. The action and controller defined in this route are merely the defaults and as you are not passing the controller as a variable it will always route to the IndexController. The action will default to indexAction but can be overridden by the route, ie:
/about -> IndexController / aboutAction
/contact -> IndexController / contactAction
etc ...
Bear in mind this will override any other routes so you need to structure your routing heirachy properly. Routes defined later in the process will override routes already defined.
For more information check the docs: Zend Framework Standard Router
I'm trying to make a route rule to make my request to the main page in kohana. It's sth of this kind: http://my_site/
And got into trouble here. In docs they write i can make this or that, lots of variants, but no example for mine. Simply saying if i try to do this way
Route::set('main/index', '')
->defaults(array(
'controller' => 'main',
'action' => 'index',
));
then if i write Route::get('main/index')->uri() on page http://my_site/hi i get a link to the same page. If i do it this way
Route::set('main/index', null)
->defaults(array(
'controller' => 'main',
'action' => 'index',
));
No result again, uri callback should have a valid value.
In official manual they suggest this variant
Route::set('default', '(<controller>(/<action>(/<id>)))')
->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));
But i need a rule with a strict match i.e. just http://my_site/, not http://my_site/(<controller>(/<action>(/<id>)))
Is there a way to help me out from this without rewriting Route class?
Thanks in advance
Route::set('main/index', '')
->defaults(array(
'controller' => 'main',
'action' => 'index',
));
Works just for for me if I make sure that route is set before any other route that may match an empty uri. Routes are checked for a match in the order they are added.
If you want to know what if your route was matched (on a development server) you can set the default controller to a non-existing one like 'bogus'. Then Kohana wil throw a Http_Exception_404 and the exception handler will serve you an error page. (Turn on kohana errors if it does not.) On that page click on the 'arguments' link of the first trace of the stack trace. You should then see something like the following:
object Request(18) {
...snip...
protected _route => object Route(5) {
protected _callback => NULL
protected _uri => string(0) ""
protected _regex => array(0)
protected _defaults => array(1) (
"controller" => string(5) "bogus" // the non-existing bogus controller default
)
protected _route_regex => string(6) "#^$#uD"
}
...snip...
}
I got the above by placing the following route before I add any other route (which could match that uri too):
Route::set('main/index', '')
->defaults(array(
'controller' => 'bogus',
));
Also make sure no other route uses the 'main/index' name as it will overwrite the older one. Actually, I just took a look at the code of Route::uri() and guess what. Static routes (routes that have no '<' or '(' in them) should return the current url. Since an empty string is a static route the result Route::uri of that route would always be only the host. Which suggests me you are overriding the 'main/index' route assuming the uri was set to an empty string.
Also when using a NULL as the uri for a route it is assumed it came from the cache and you end up whith an empty route when it did not came from the cache.
Your Route::get('main/index')->uri() returns a relative uri, which in this case would be an empty string. What you want to do is use the url method of the Route class: Route::url('main/index'). This will give you an url that has gone through Url::site as well.
I'm try to create search engine friendly URLs for the pages controller, i.e. /about instead of /pages/about.
I've tried setting up the following routes (at the bottom of routes.php):
Router::connect('/*', array('controller' => 'pages', 'action' => 'display'));
and
Router::connect('/:page', array('controller' => 'pages',
'action' => 'display'), array('pass' => array('page'), 'page' => '[a-z]+'));
Both properly match /about, /support, etc. However, failed when I had a action/method pair. For example, /contact should route to PagesController->contact(). However, the above routed it to PagesController->display().
There has to be a way to accomplish this without making a specific route for each page. How can I create a route or set of routes that:
Mimics the default route behavior for
the PagesController. That is routes
to display() unless a action/method
pair exists.
Does so with search engine friendly URL. That is coming from root / not /pages.
Demonstrate both the Router::connect() and Html->link()
I have checked for examples in the CakePHP Book and viewed other questions such as CakePHP routing in pages controller. Nothing seems to satisfy the specification above.
You need to create a second route for the contact method call and put it before the more generic rule to match "everything [a-z] after /pages". Try that before your rule:
Router::connect('/contact', array('controller' => 'pages', 'action' => 'contact'));
Always keep in mind that the order of routes is important. The more generic a rule is the more will it match. So put more specific rules in front of the more generic ones.
Would like http://websites.com/users/username1 URL structure
In your app/config/routes.php file you could add:
Router::connect('/users/*', array('controller' => 'users', 'action' => 'index'));
This would route all requests to /users/ to the index action of the users controller. If you want to use a different action, just replace 'index' with the action you prefer to use.
More info is here:
http://book.cakephp.org/view/46/Routes-Configuration