Using CakePHP 2.3. I turned on the security component, and I noticed an odd behavior with postLinks, where for some reason they are no longer seem to be transmitting data by POST, but instead they are using GET. In the action I'm trying to call, the first thing I do is to ensure that the data was made by POST:
if (!$this->request->is('post'))
{
throw new MethodNotAllowedException();
}
When the security component is on, this if statement is false. When it is off, the if statement is true. No other changes have been made.
The postLink:
<?php echo $this->Form->postLink($this->Html->image('icons/resend-icon.png'), array('action' => 'resend', $invoice['Invoice']['number']), array('escape' => false, 'class' => 'hastip', 'title' => 'Resend'), __('Are you sure you want to resend this invoice?')); ?>
As far as I've been able to look, I've found no explanation for this. I would prefer if I could make sure the data is actually being sent by POST, though everything else works if I remove the check for the request is a POST.
Edit:
I've discovered that if I set $this->Security->csrfCheck = false; and $this->Security->validatePost = false; in the before filter for that particular action, it does not have this problem. I would still like to know why precisely this is though.
Edit 2:
After more investigation, I discovered the view of the page in question has another form on it, echo $this->Form->create('Invoice', array('type' => 'get')); which should not be affecting the post links in any way (post links are not inside the form, etc.), but if I remove the array('type' => 'get'), the postLinks start working. I need the other form to be of type get though, as it's a search form, and I need to have the search query string in the URL.
Edit 3:
I've discovered that moving the search form below the post links also fixes the problem. I tried running the markup through a html validator to make sure nothing was malformed, but it did not report anything.
Edit 4:
I discovered that the markup being generated for the PostLinks is incorrect -- the hidden inputs used for detecting CSRF are named incorrectly, resulting in it failing CSRF tests. Thus, the request is getting blackholed. I have set up a blackhole callback to redirect http:// to https://, so the page gets redirected, resulting in a new get request for the same page, which then gets rejected by the MethodNotAllowedException. Trying to investigate now why the PostLinks aren't being generated correctly.
I determined the solution is after finishing with the first form, I needed to reset the Form helper's request type.
<?php echo $this->Form->create('Invoice', array('type' => 'get')); ?>
<?php echo $this->Form->end(); ?>
<?php $this->Form->requestType = null; ?>
$this->Form->requestType starts as null, and gets set by calling $this->Form->create. So if I set the earlier Form to be post, or if I had created the Form after using postLinks, the Form helper's request type is set to a value that will work with PostLinks when I attempted to create the postLinks, but it appears manually resetting requestType also works.
Edit: This is actually a bug with the CakePHP framework. I have reported it, and it has been fixed, so this is no longer necessary in the newest version of CakePHP.
Related
Since whole a day I have been trying to search for best solution to redirect to same page where it is requested. Means I have a edit action page. I can move on this page from anywhere either it is detail, view, latest, recent or from any other action I can move to edit action. What I want is I want to move to last action again where it is redirected from. While googling I got solution to put
`$this->redirect($this->referer());` //or
`$this->redirect(Controller::referer());`
to use in controller to move to but it reverts to edit page again as it is navigated from that only.
Other solution told me to use hidden variable whose value it
`echo $this->Form->input('Song.referer', array('type' => 'text', "value"=>$this->request->referer()));`
like this and request to this variable on successfull edit that is OK. But it fails in case of validation put on controller as same page is open in case of error so my referer change. What shall be best practise in this case. Should I save session in and every call to main my referrer or something other available with cakephp 2.3
I use this method:
when I create a link to my edit page in my action i add a 'referer' param
$this->Html->link('Add', array('action' => 'add', 'referer' => 'detail'));
in my controller then I read the value of referer and i redirect to the right page after saving the data, even in case of validation error the value of referer remains in the url of the page
It's not a great solution since it's not transparent to the user who see the url and can change the referer changing the url itself. But it works and it's simple to implement
Save the last location in hidden field eg.
$this->request->data["Business"]["referer"] = $this->referer();
Now put optional condition on save function to redirect on the page like this.
if ($this->Business->save($this->request->data)) {
(isset($this->request->data["Business"]["referer"]) && !empty($this->request->data["Business"]["referer"]) ? $this->redirect($this->request->data["Business"]["referer"]) : $this->redirect(array("action" => "index"));
}
My codebase is built in Cakephp.
I have an update button which processes a "notes" field. I have a working controller update/write that redirects back to the page, so the "hard" bit is done...
However: from a usability point of view, this redirects to the raw URL, and hence to the top of the page every time.
The <input> field has an id, so I simply want to link back to it using an anchor tag.
Here's what works [controller]:
$this->redirect('/review/index/'.item->getEmployeeId());
I tried to add in the following:
$this->redirect('/review/index/'.$item->getEmployeeId().'#'.$item->getEmployeeId());
However - this seems to be stripped out... The write still works, but the anchor is stripped out.
For debugging/quick gotchas: I have tested the raw URL out and it redirects to the <input>.
Is there another way to do this? I'm assuming this is some cakephp "magic" and I simply don't know how to apend an anchor. Some google searches and poking in the API don't seem to clear things up though.
Many thanks.
Following: http://book.cakephp.org/2.0/en/controllers.html#Controller::redirect
Use this:
$url = array(
'controller' => 'review',
'action' => 'index',
$item->getEmployeeId(),
'#' => $item->getEmployeeId()
);
$this->redirect($url);
I have a view which interacts with more than one controller (post, comments, categories...)
In case the comment is not empty, it would go to the same action (comments/add) but in this case i manually redirect them again to the previous view with something like this:
$this->redirect(array('controller' => 'posts', 'action' => 'view', $this->request->data['Comment']['posts_id'], '#' => $this->Comment->id));
The thing is, when they try to post an empty comment, for example, the validation of Comment redirects it to comments/add (which is the route on the form action) but i don't want the redirection to do this. I want it to come back to the original view and i don't have anyway to change it on the controller or the model (as far as I know)
Is there any way to do this?
Thanks.
The easiest way to do this is to make your form submit via AJAX. So you don't refresh the whole page on submit - you just get the form back, with errors (if there are any).
Obviously, that won't work for users without Javascript. So you can either not worry about those users, or you can make it so the add method of your comments controller uses the view that you want. Something like this:
if ($this->request->is('ajax')) {
$this->render('/Elements/comment_form');
return; // return the form only
} else {
$this->render('/Posts/view'); // Your post view.ctp would have the comment form on it.
}
Here's an example of a page where I've used that method: http://www.lintonmeagher.com/contact Try submitting either one of the forms with no data.
Let me know if you need any more info.
I am trying to create a subscribable web cal. The file works, if I link to it directly. But when generated out of CAKEPHP, even with a blank layout, the calendar program says the data is invalid. I am guessing there are some hidden headers, data, something that cakephp is sending in the background. Any way to have cakephp just send the actual file?
Any other ideas why I can't subscribe?
Make sure that you put Configure::Write('debug',0); in the action in your controller that returns the data for the calendar. And then make sure you call a layout that ONLY has <?php echo $content_for_layout; ?> and nothing else in it using $this->layout = ‘yourlayout’; in that same action in the controller.
I am trying to do some custom routing on my site, but have been stuck for 2 days at a very silly issue. I have the following route configuration:
Router::connect('/your-solution/add-comment/*', array('controller' => 'comments', 'action' => 'add'));
Router::connect('/admin/your-solution/add-comment/*', array('controller' => 'comments', 'action' => 'add', 'admin' => true));
The problem is that when I try to load a URL formatted using the second route, it gives me a 404 not found.
The first rule works fine.
For both rules I have a separate element containing a form and pointing to a URL formatted after the respective rule. The only parameter for both actions is the solution id, which is "contained" in the wildcard.
What could possibly be the issue? Thank you very much for your help!
EDIT:
I found out another weird behaviour. When I access /admin/your-solution/add-comment/3, it goes to that action. But if I submit a form to that link, it displays a blank page, with Firebug informing me that the page was not found. Very strange...
Also, I have a similar route for editing comments. Both loading the edit form and saving the form work...
how are you?
In order to see exactly why isn't it working, go to your /app/config/core.php and seek for this line:
Configure::write('debug', 2);
And make sure the value is set to "2". This way, it'll no longer give you a 404 error, but the actual issue, since in production mode (debug set to 0), all errors are masked with a 404 error.
Let me know!
Cheers!
In your core.php be sure
Configure::write('Routing.prefixes', array('admin'));
In your comments controller, be sure you have
function admin_add() {...}
Also try other ways of formatting Routing statement.
Router::connect('/admin/your-solution/add-comment', array('controller' => 'comments', 'action' => 'add', 'admin' => true));
The order of your route is also important. You may want to check that.
For debugging which route you are using when loading the URL, try adding this code to your app_controller.php file.
function __construct() {
$route = Router::currentRoute();
pr($route);
}
These are just some tips to hopefully help you move forward.
Apparently, the problem has been lying in a disabled input. After I've deleted this element, the form submits correctly and the target page is shown.
Just for my knowledge, why didn't the form submit if it had a disabled input in it?