cakephp router change url and params - cakephp

I want to use router.php to change URL ( In CakePHP version 2.1.3):
Currently, I have URL like:
http://domain.com/register/add?userName=123&fullName=abc
Now I want to change (rewrite) that URL to new :
http://domain.com/regis-new?cus_name=123&cus_full_name=abc
My code in Controller:
class RegisterController extends AppController{
function index(){
$userName = $this->request->query['userName'];
$fullName = $this->request->query['fullName'];
}
}
How i can config router to apply new URL?
Thanks

Router::connect('/regis-new/*',
array(
'controller' => 'register'
'action' => 'add' // or new action name
)
);
When you put start after alias means that pass any thing after alias.
The parameters doesn't have any thing to do with Routing.
:) Now check your input names in your view. e.g. if the input name was "userName" rename it to "cus_name"
echo $this->Form->input('cus_name' array(
'name' => 'cus_name'
));
Make sure when you get input values by their new names. e.g. in your action:
$this->request->data["cus_name"];

Related

Plugin route to a prefixed controller

I'm creating a plugin for my application (using CakePHP 2.6.0) that allows users to login into a user area using the same model as for the admin area, so I'm trying to get the same type of URI scheme as the admin area e.g. /admin/users/login but then for /special/users/login. I have the following route in my plugin's Config/routes.php and added the 'special' prefix to the 'Routing.prefixes' configuration:
Router::connect('/special/:controller/:action', array(
'special' => true,
'prefix' => 'special',
'plugin' => 'Special',
'controller' => ':controller',
'action' => ':action',
));
With above route and entering the following url /special/users/login it would make sense to me right now if Cake went for Plugin/Controller/SpecialUsersController.php (considering namespace conflicts with the main application's UsersController) but instead I get an error Error: Create the class UsersController.
Is there a built-in way for it to load a prefixed controller (without changing the url) based on the plugin? Or is there a better way to neatly extend my main application? Am I going about this the wrong way?
I could not find a built-in way for it to work as I wanted to so I changed the way URL strings were parsed using a custom route class in my app's Routing/Route/ folder:
App::uses('CakeRoute', 'Routing/Route');
/**
* Plugin route will make sure plugin routes get
* redirected to a prefixed controller.
*/
class PluginRoute extends CakeRoute {
/**
* Parses a string URL into an array.
*
* #param string $url The URL to parse
* #return bool False on failure
*/
public function parse($url) {
$params = parent::parse($url);
if($params && !empty($params['controller']) && !empty($params['plugin'])) {
$params['controller'] = $params['plugin'] . ucfirst($params['controller']);
}
return $params;
}
}
And then setting up my plugin routes as:
App::uses('PluginRoute', 'Routing/Route');
Router::connect('/special/:controller/:action', array(
'special' => true,
'prefix' => 'special',
'plugin' => 'Special',
'controller' => ':controller',
'action' => ':action',
), array(
'routeClass' => 'PluginRoute'
));
This resulted in /special/users/login creating the controller I wanted Plugin/Controller/SpecialUsersController.php, no side effects so far. Extending the main application's UsersController is a different story though.
Maybe someone else has use of this or knows a better solution?

how to rander .html file using cakephp : CakePHP

I am working on CakePHP and I have a URL http://admin.example.com/Pages .
How can I create http://admin.example.com/Pages.html ? Is there any solution or component to solve this issue?
According to CakeBook , You can define extensions you want to parse in routes
E.g. Write the code below in app/Config/routes.php
Router::parseExtensions('html');
This will allow you to send .html extenstion in routes(url)
Not create a link
E.g:
$this->Html->link('Link title', array(
'controller' => 'pages',
'action' => 'index',
'ext' => 'html'
));
When you click that link you will get url in browser something like this
http://admin.example.com/pages/index.html
Do you really need this? CakePHP is automatically render view files from View folder
You can create (if its PagesController and index methond) index.ctp in app/View/Pages folder and it will be automatically render.
You can use file_get_contents function to read files. Something like this:
// in controller
function index() {
$content = file_get_contents('path/to/file.html');
echo $content;
die();
}

How to connect a post rest request to the add controller action using prefixes in cakephp

I code a client/server application.
Server side is powered by CakePHP 2.4.7.
Client side run with angularjs and cordova on mobile devices
I use several cakephp route prefixes whose 'admin' and 'mobile'.
(And I use $resource and $httpInterceptor angularjs factories to setup my REST requests.)
I want to call /website/mobile/posts/add.json with json data posting.
So I call /website/mobile/posts.json with a POST ajax query:
The problem is here: the called controller action is 'index', not 'add';
On top of my PostsController, I added this:
echo $this->request->params['action'] . "\n";
echo ($this->request->isPost())? "post" . "\n" : "not post";
die;
and the response is always:
mobile_index
post
So the ajax request seems correct but cakephp don't map it to the add action, but index one.
However my configuration seems good too; here is a fragment of my routes.php
Router::mapResources(array('users','posts'));
Router::parseExtensions('json');
Any idea ?
Prefix routing doesn't work with REST routing out of the box
REST routing works by automatically creating routes for the controllers passed to Router::mapResources(). Prefix routing pretty much does the same, it creates default routes including the prefixes defined in Routing.prefixes.
However both functionalities don't know about each other, they both create separte routes, so Router::mapResources() will connect to URLs without prefixes (the prefix option for this method is not using actual prefix routing, it will just add the value of that option to the beginning of the URL to connect to!), and therefore your request to /mobile/... doesn't actually use REST routing but only prefix routing.
Defining prefixed REST routes manually
There is no simple fix for this problem like using an option or something, instead you'll have to define the REST routes manually so that the prefix option is included, simple enough though.
See Modifying the default REST routes and Custom REST Routing.
A sample Route could look like this:
Router::connect(
'/mobile/users',
array(
'prefix' => 'mobile',
'mobile' => true,
'controller' => 'users',
'action' => 'add',
'[method]' => 'POST'
)
);
This would connect POST requests to /mobile/users to UsersController::mobile_add(). Similary you'll have to do this for all other methods like GET and PUT, with and without passing an id, etc.
Note that when connecting manually you can ditch the Routing.prefixes option and of course the call to Router::mapResources().
Automated mapping
Defining all those routes by hand is kinda exhausting, you're better of automating it with respect to the Router::resourceMap() configuration.
Here's an example on how to do that, it's somewhat similar to Router::mapResources(), but it accepts a prefix option that actually makes use of prefix routing:
function mapResources(array $controllers) {
$resourceMap = Router::resourceMap();
foreach($controllers as $controller => $options) {
if(!is_array($options)) {
$controller = $options;
$options = array();
}
$options += array(
'prefix' => null,
'plugin' => null,
'id' => Router::ID . '|' . Router::UUID
);
foreach($resourceMap as $params) {
$url = '';
if($options['prefix']) {
$url .= '/' . $options['prefix'];
}
if($options['plugin']) {
$url .= '/' . $options['plugin'];
}
$url .= '/' . $controller;
if($params['id']) {
$url .= '/:id';
}
Router::connect(
$url,
array(
'prefix' => $options['prefix'],
$options['prefix'] => !!$options['prefix'],
'plugin' => $options['plugin'],
'controller' => $controller,
'action' => $params['action'],
'[method]' => $params['method']
),
array(
'id' => $options['id'],
'pass' => array('id')
)
);
}
}
}
You would call it like this:
mapResources(array(
'books' => array(
'prefix' => 'mobile'
)
));
and it would map all the REST routes for your books controller using the mobile prefix.

CakePHP 2.0 Router::connect issue without visible id in url

I want following SEO url like:
www.example.com/users/profile/webfacer
I do not want to use the unique user to fetch from database.
I try to use the Router method connect in my AppController. but I realised that it isn't possible (or not knowing it right now to use it in their also used in routes.php does not helped) like this:
//in AppController
Router::connect('/users/profile/:name',
array(
'controller' => 'users',
'action' => 'profile'
) ,
array(
'pass' => array('id', 'name'),
'id' => '[0-9]+'
)
);
How can I reproduce this link (below the example) with this html link helper to send the id but not show it in the url:
$this->Html->link('webfacer',array(
'controller'=>'users',
'action'=>'profile',
'id'=>1,
'name'=>'webfacer'
));
This would output www.example.com/users/profile/username:webfacer that mean my router doesn't appear to my route options.
Has anybody had the same issues and solved this?
Because you haven't put the :id argument in your route string, Cake won't know what to do when you pass it in the helper, that is why it's just appending it as a normal param in the URL. There is no way to pass a "hidden" id with the URL, you're best bet is to either expose it or at the other end of the app write something that fetches the ID based on the username you pass (make sure this column is indexed and url-safe).
I would just simplify your route to this:
//in AppController
Router::connect('/users/profile/:name',
array(
'controller' => 'users',
'action' => 'profile'
) ,
array('pass' => array('name'),
)
);
And don't bother passing ID to the helper. In your profile action you'd just have something like this:
public function profile($name) {
$user = $this->User->find('first', array('conditions' => array('name' => $name)));
}

CakePHP - Using the RSS Helper without RequestHandler Component

I have set up the RSS Helper (with CakePHP 1.3.4) and all is working - I can access my feeds by /news/feed.rss - as exampled at http://book.cakephp.org/view/1461/Creating-an-RSS-feed-with-the-RssHelper
But I want to be able to do this conditionally, in sudo, something like:
if (!empty($var)) {
switch ($var) {
case one :
$xml = $this->method->find('$var conditions...');
... use RSS Helper to serve results as XML.
case two :
$xml = $this->method->find('other $var conditions...');
... use RSS Helper to serve results as XML.
}
}
Can I use the RSS Helper in this circumstance? What calls/syntax do I use?
There are 2 ways to do this.
Basically you can pass a variable like this:
http://yourserver.com/news/feed.rss?recent=20
and then in the controller you can access this variable with
$this->params['url']['recent']; //20
Or you can add a line in your Router file like this:
Router::connect('/feed-:recent/*', array('plugin'=>false, 'controller' => 'news', 'action' => 'feed'), array('recent'=>'[0-9]+'));
This way your url will look like:
http://yourserver.com/news/feed-20.rss
and finally I believe that url like this will work as well:
http://yourserver.com/news/feed.rss/recent:20
You can pass params to the function the same as any other controller call.
IE
public function rss( $limit = 20, $topic = null ){
if( !$topic ){
$xml = $this->Article->find( 'all', array( 'limit' => $limit ));
...
} else {
$xml = $this->Article->find( 'all', array( 'limit' => $limit, 'conditions' => array( 'Article.topic' => $topic )));
}
...
}
}
?>
Then you can access the rss feed with: http://domain/articles/rss.rss
If you need to pass parameters: http://domain/articles/rss/100.rss (fetch all with 100 results)
Or like this: http://domain/articles/rss/10/obama.rss (fetch all with the topic "obama" and return 10 items.
The RequestHandler allows you to use a url like /posts/index.rss and it automatically loads the RSS Helper and sends the output to /views/posts/rss/index.ctp, and uses layout at /views/layouts/rss/default.ctp.
But if you want to use the RSS Helper on it's own you need to:
1) include it the controller
var $helpers = array('Rss');
2) in your controller action you need to specify where the output goes, so
$this->render('/posts/rss/index','/rss/default');
In this case I also specified which layout to use in the 2nd argument. The first arg - the index.ctp file location is relative to your views/ directory. The second arg - the layout is relative to your views/layouts/ directory.
So I have a method in my posts_controller that I use to identify which feed is wanted (through a passed var) and subsequently finds the posts and sends them to the correct views and layouts:
function rss(){
if (!empty($this->params['pass'])){
$ops=array(
'conditions'=>'where feedname_id=' . $this->params['pass'][0],
'order' => 'Post.created DESC',
'limit' => 10
);
$this->set('posts', $this->Post->find('all',$ops));
$this->render('/posts/rss/index','/rss/default');
} else {
$this->redirect(array('controller'=>'feednames','action'=>'index'));
}
}
There might be better ways to code this - if so please let me know.

Resources