Controller redirect with variables and/or messages

Permalink
Hi there -

I've looked around a bit and can't seem to find a solid answer regarding this question of mine. Perhaps I'm thinking too hard about it so I figured I'd post to see what others thought. Here goes.

When building single pages I have my associated controller. Great. Let's say I have a form that posts to a method in this controller. Let's call this method:

public function processForm() {  
// ...do some stuff here, database, etc
}


After I've processed the form typically I will want to provide a message to the user saying "Successful" or "Error", or, save a variable (like a MySQL Insert ID) for additional steps in a process (another form to fill out). However, to do this, I found that when I do something like:

public function processForm() {
//...do some stuff here, database, etc.
$this-set('message','Step 1 is complete.');
$this->redirect('/form_step2');
}


I lose the "message" variable. I've looked to see if I can pass variables or an array of some sort to the redirect variable but I don't think I can (hopefully I'm wrong). This has been tricky and arduous for me when trying to submit to another controller. When I'm working within the same controller I've been doing something like this:

public function processForm() {
//...do some stuff here, database, etc.
$this->step2();
}
public function step2() {
$this->set('message','Successful post.');
$this->render('my_custom_view');
}


I'm not sure if all of this is a matter of preference and how I setup my controllers and logic etc. I know that within the same controller view file I can use all kinds of switches and get the task of the controller and render different content, but I'd like to use the render() method as I think it helps separate different content and is less cluttered in terms of code.

I'd like to hear what others are doing. I'd love to hear your thoughts.

Thanks!

stephendmalloy
 
stephendmalloy replied on at Permalink Reply
stephendmalloy
So after looking in concrete/core/libraries/controller.php the redirect method does allow me to pass parameters (duh!)

/** 
    * Redirects to a given URL
    * @param string $location
    * @param string $task
    * @param string $params
    * @return void
    */
   public function redirect() {
      $args = func_get_args();
      $url = call_user_func_array(array('View', 'url'), $args);
      if ($url == '') {
         $url = BASE_URL . DIR_REL;
      }
      header("Location: " . $url);
      exit;


However, I'm still not sure how to pass along large sets of data, for example, the complete contents of a form submission for further processing to an additional controller.
Phallanx replied on at Permalink Reply
Phallanx
The second parm is the task (function) in the targeted controller. The third parm is the arguments for that task.

So assuming that your step2 function in in the controller for myform, you can do things like this

$this->redirect('myform','step2',$_POST);
stephendmalloy replied on at Permalink Reply
stephendmalloy
Anyone?
JohntheFish replied on at Permalink Reply
JohntheFish
A trick I have used is to put messages or errors into the session data, then subsequently check the session data for messages and clear them.
stephendmalloy replied on at Permalink Reply
stephendmalloy
John -

I was going to use sessions too, however I thought there must be a better way. Guess not :)

Thanks for your response, I really appreciate it.
simonknibbs replied on at Permalink Reply
simonknibbs
I Know that this is quite an old post, but i am currently experiencing this problem. Is there anyone who has thought of away to pass the error? or is it only possible to do using session data?
ThomasJ replied on at Permalink Reply
ThomasJ
I am struggling with a redirect back to th same page using $this->redirect('this-page-handle', 'errors_passsed', $errors_array) where errors_passsed = public function errors_passsed() in the block controller. The only thing that works is $this->redirect('this-page-handle'). any other paramiters placed in the instruction result in a '404, Page Not Found" redirect. $this->redirect(pageHandle,function,dataArg) doesn't work for me. I wish I could find a detailed instruction of how to use the redirect() function and where it is proper to use it. And if there is better approach to recall the same page from a block controller while passing arguements back for display.

Also, I don't understand the redirect function code. I've never seen this before. how does calling a method with 3 paramiters passed in it's arguements get passed to a method that has no arguement template. Wouldn't it be a lot more simple and clear reading to just put the args in the method's template with defaults preset? And, how do these args get picked up by func_get_args() and call_user_func_array()? I know that I still have a lot to learn but this one has me really stumped.
stephendmalloy replied on at Permalink Reply
stephendmalloy
ThomasJ -

Not sure how you've programmed all of this - but consider rendering the default view in the method of the controller you are calling while looking for a errors var set using $this->set('varName','value'); Then check for them in the view. This is sort of a hack, too (as far as I know anyway). Another alternative is to use session data as John suggested.

I tend to try to encapsulate as much CRUD functionality into one view -> controller as possible and use $this->getTask('method_name'); to render accordingly (i.e. edit / add ).
ThomasJ replied on at Permalink Reply
ThomasJ
Thank you so much for responding.

This block that I am working on is an adaptation of concrete5's registration form. When the form is submitted with <form action="<?php echo $this->action('do_register'); ?>" method="post"> in the block's view script, it is sent to "public function action_do_register()". There, I process and validate the form's input data and if there is any errors, I am trying to use $this->redirect('form-page', 'returned_errors', $errorsArray) which I believe should be sending the registrant back to the form page and to a method in the block's controller called "public function returned_errors($errors)" ...-...-...-...-...???

While writing this as a step by step process in the big picture and with a fresh, clear mind starting out this morning, I think that I see what is wrong with this picture and why the Register Form was made as a single page and not a block form.

On the call back to the form's page, concrete5 doesn't see the embedded block's controller while looking for the called method. It just checks for a method in the theme's default page controller (what ever that is) and doesn't find it. That is why c5 throws a 404 error as a result of the redirection. If I am wrong with this hypothesis, please tell me that I am all wet. If this is true, I'm going to have to leave it as a single page.

As for using sessions, I thought of that as a last resort fix but I'd rather not use cookies to pass the data and keep the process server side.
ThomasJ replied on at Permalink Reply
ThomasJ
This is an old post but I came up with a solution to the problem of redirecting with a posting to another page and not using sessions.

public function on_before_render() {
      $u = new user();
      if ($u->isLoggedIn()) {
         $form = Loader::helper('form');
         echo '<form id="loggedIn" method="post" action="'.View::url('/logged').'" ></form>'.
               $form->hidden("forwardTo", "/profile").
               $form->hidden("returnTo", "/register").
             '</form> <script>document.getElementById("loggedIn").submit();</script>';
      }
   }

This method I use redirects the visitor while posting URLs for the next page to redirect() to if the visitor is already logged in. That page is where he selects whether to continue as that logged in user or get logged out and return to the registration process.

The part that actually performs the redirect is the echo command that writes a short hidden form to the browser with an automatic submit in a JavaScript nibblet. On the next page, these fields will be available as $_POST['returnTo'] and $_POST['forwardTo'].