Is there a way to make a Zend Framework Application to act like Facebook in profile links? - zend-framework

My accurate question would be, is there any routes that can make possible that when i go
mydomain.com/profilename
it'd be redirect to the profile controllers instead of index, and sitll, if i provide no parameter, he'd load the index page, and even still, if theres a controller by that name, that he'd run that controller instead of searching for a profile...
Pretty much complicated i know, that's why i'm asking for your help, you geniouses! <3
Thanks in advance, Jorge.

ZF1 doesn't have route priority as such, but routes are matched LIFO (last in, first out). So as long as you were able to hard code controller names into your routes, and put this after your profile route, you could do something like this:
$router->addRoute('profile',
new Zend_Controller_Router_Route('/:profilename', array(
'module' => 'default',
'controller' => 'profile',
'action' => 'view'
))
);
$router->addRoute('something',
new Zend_Controller_Router_Route('/:controller/:action', array(
'module' => 'default',
'action' => 'index'
), array(
'controller' => '(foo|bar)' // names of your controllers
))
);
Alternatively, if this isn't possible, or you want a more robust (but more difficult) solution, I wrote a blog post a while back with a detailed explanation of how to achieve this with a custom route class: http://tfountain.co.uk/blog/2010/9/9/vanity-urls-zend-framework

Related

How to access two similar but located in different API in a single Apigility project?

Suppose we do have an Apigility URL like localhost:8888/user.
But I do have two API's in a single Apigility project, ApiOne and ApiTwo.
Doing a GET request from localhost:8888/user always returns resources generated by ApiTwo. But when I want to get the same user resource rom ApiOne because it is from a different DB I can't retrieve it. I already tried to supply the Accept media type with the proper version (hoping it would help), to access ApiOne (e.g. Accept application/vnd.apione.v1+json)
I'm guessing based on your question that you've got ApiOne with a route to /user and ApiTwo with a route to /user?
The problem is that they are not different routes. ZF2 is going to use (I believe) the one that is defined last in the combined configuration file. If you want to be able to use both API resources, you'll need to have different routes somehow. This could be literally changing one of them to something like /user1.
You could also theoretically route to two different endpoints for entities if you provide constraints on the id that would make them differentiable. What I mean is you could have both routes like this:
/api/user[/:user_id]
/api/user[/:user_name]
As far as the ZF2 router is concerned, at this point, those routes are identical. The variable parts user_id and user_name could be the same thing.
However, you'd need something else that makes the routes different. Apigility (and ZF2) allow for constraints on the parts of the URL. So you could put a constraint on user_id of [0-9]+ and a constraint on user_name of [a-z]+. These would make the routes mutually exclusive for entities, but the collection version of the routes is still the same.
Constraints are added in the route under options like so:
'router' => array(
'routes' => array(
'your-api.rest.user' => array(
'type' => 'Segment',
'options' => array(
'route' => '/user[/:user_id]',
'defaults' => array(
'controller' => 'YourApi\\V1\\Rest\\User\\Controller',
),
'constraints' => array(
**'user_id' => '[0-9]+'**,
),
),
),
'your-api.rest.username' => array(
'type' => 'Segment',
'options' => array(
'route' => '/user[/:user_name]',
'defaults' => array(
'controller' => 'YourApi\\V1\\Rest\\Username\\Controller',
),
'constraints' => array(
**'user_name' => '[a-z]+'**,
),
),
),
),
),
)
In this example, if no user_id or user_name were provided, the Username resource should be called since it is defined last.
Overall though, my recommendation would be that you change the routes so that they are different. The accept header with version is essentially used for versioning, not routing to a different API resource.

Get nested ressources when using cakePhp restfull

I'm using cakePhp to create a Rest api (see http://book.cakephp.org/2.0/fr/development/rest.html) and I need to get nested resources. The documentation tells how to get let's say books implementing a URI /books.json. But does not tell how to get for example reviews for a given book. What I'm trying to make is somthing like this: /books/14/reviews.json that returns Review resources.
Can any one tell me hwo to make this?
See the Custom REST Routing section of the docs you've linked. In case the default routing doesn't work for you, you'll have to create your own custom routes that either replace or extend the default ones.
Your /books/14/reviews.json URL could for example be mapped to BooksController::reviews() likes this:
Router::connect(
'/books/:id/reviews',
array(
'[method]' => 'GET',
'controller' => 'books',
'action' => 'reviews'
),
array(
'id' => Router::ID . '|' . Router::UUID,
'pass' => array(
'id'
)
)
);
When placed before Router::mapResources() it should work fine together with the default routes.

How to assemble a URL back to the www route when inside a Zend_Controller_Router_Route_Hostname route?

I have spent hours trying to find a solution to this but doesn't appear to be much out there.
I currently have admin.domain.com point to the admin module which is easy to do like so:
$adminRoute = new Zend_Controller_Router_Route_Hostname(
'admin.domain.com', array(
'module' => 'admin'
)
);
$router
->addRoute('admin', $adminRoute->chain(
new Zend_Controller_Router_Route(
':controller/:action/*',
array(
'controller' => 'index',
'action' => 'index'
))
));
And all other routes will work as per the default routing so that www.domain.com/module/controller and www.domain.com/controller both work as expected.
However, if I am currently inside the admin module and want to assemble a URL which points back to the www.domain.com route, then how does one do this?
Unfortunately it's not a simple case of making the default route a Hostname route for www.domain.com because then you don't benefit from the 'optional' module param in the path. E.g.
$wwwRoute = new Zend_Controller_Router_Route_Hostname(
'www.domain.com', array(
'module' => 'default'
)
);
$router
->addRoute('default', $wwwRoute->chain(
new Zend_Controller_Router_Route(
':module/:controller/:action/*',
array(
'controller' => 'index',
'action' => 'index'
))
));
Will simply build all paths in the format www.domain.com/default/controller/action rather than www.domain.com/controller/action
The docs suggest that the default routing uses Zend_Controller_Router_Route_Module but i've tried that and it seems there's more to than just that.
Any ideas?
EDIT: I'm suspecting that you either need to do one way or the other i.e. have all modules on a subdomain and then route the requests strictly like so /controller/action/*, or, have modules as part of the route path. Otherwise, a module would be reachable via two URLs - module.domain.com and www.domain.com/module - obviously there are ways round this, and of course, you could just set up specific routes for each module thereby not relying on the 'optional' module feature of the default Zend routing.

Zend Routing / URL helper . Have a global parameter show up first in URL

Was curious if anyone knew the best way to implement the following: I have a parameter in my zend framework 1.12 app which effectively controls the 'scope' of things, and is a field in every table in my db to represent the scope of a row. It is a simple integer variable, and can be thought of as 'buildingID', so it controls which 'building' we are working with.
In a plugin, I have:
Zend_Controller_Front::getInstance()->getRouter()->setGlobalParam('building', DYNAMIC_INT);
which accomplishes what I need. When I build a URL with the URL view-helper I have my parameter, but it is always at the end of the parameter list. I know this is trivial from a programming perspective, but how would I achieve 'prepending' this global param to my url parameters?
site.com/admin/controller/action/param1/xyz/param2/xyz/building/2
to become
site.com/admin/controller/action/building/2/param1/xyz/param2/xyz ?
Open to any ideas. If you want me to overload the url view helper, can you provide some example code, because I had trouble setting up this class.
Thank you all!
You can use a custom route to accomplish this. Setup the route somewhere in your bootstrap file:
$route = new Zend_Controller_Router_Route(
':controller/:action/building/:building/*'
);
$router = Zend_Controller_Front::getInstance()->getRouter();
$router->addRoute('building', $route);
And then, assuming that the following has been called at some point prior to using the url view helper...
Zend_Controller_Front::getInstance()->getRouter()->setGlobalParam('building', DYNAMIC_INT);
...you can specify the route as the second argument of the helper:
echo $this->url(array(
'controller' => 'admin',
'action' => 'controller',
'param1' => 'xyz',
'param2' => 'xyz',
), 'building');
// /admin/controller/building/1/param1/xyz/param2/xyz

Zend Framework - routes - all requests to one controller except requests for existing controllers

How to create route that accept all requests for unexsting controllers, but leave requests for existing.
This code catch all routes
$route = new Zend_Controller_Router_Route_Regex('(\w+)', array('controller' => 'index', 'action' => 'index'));
$router->addRoute('index', $route);
how should I specify route requests like /admin/* or /feedback/* to existing adminController or feedbackController?
You should not create a route to handle that. The error controller will take care of all three kinds of the following errors:
Controller does not exist
Action does not exsist
No route matched
Take a look at the documentation on how to use it correctly:
http://framework.zend.com/manual/en/zend.controller.plugins.html#zend.controller.plugins.standard.errorhandler.fourohfour
I found only the way - not to add route in case current request is about admin area
$request = $frontController->getRequest();
if (!preg_match('/knownController/', $request->getRequestUri())){
$router->addRoute('index', new Zend_Controller_Router_Route_Regex('(.*)', array('controller' => 'index', 'action' => 'index')));
}
You can also use the ErrorController to do a similar thing. Maybe if you dig into the way they implement the plugin it will help you build something that meets your needs closely?