Laravel - Calling Redirect::to() from within view

ArranJacques picture ArranJacques · Sep 17, 2013 · Viewed 11.7k times · Source

I'm currently working on a cms which is built on the Laravel 4 framework. I'm trying to build a plugin system, similar to Pyro CMS, where module views can be included in a page view using the Blade template system.

I'm building a contact form plugin that if submitted successfully will redirect the user to a given url, or simply redirect back to the existing page.

The code for my contact form class is:

class Contact {

public static function form($params)
{
    //get params and execute relevant logic here

    $redirect = isset($params['redirect']) ? $params['redirect'] : Request::url();

    $data = Input::all();

    if($data)
    {
        // Run validation and send message here
        return Redirect::to($redirect)
    }

    return View::make('contact_form_view');
}

}

There is a page controller that will display the appropriate page view depending on the route used and the idea is that a user can drop a contact form into any page template and easily customise it by calling the form function from within the template view as shown below

<html>
    <head>
    </head>
    <body>

        {{ Contact::form(array(

            'to' => '[email protected]',
            'view'  => 'contact_form_1',

        )) }}

    </body>
</html>

This all works fine apart from the redirect. When the form is successfully submitted and the message sent the page refreshes and displays the following message in place of the contact form

HTTP/1.0 302 Found Cache-Control: no-cache Date: Tue, 17 Sep 2013 09:14:16 GMT Location: http://localhost:8888/my_initial_route Redirecting to http://localhost:8888/my_new_route.

About 2 seconds later the redirect then takes place and the browser is redirected to whatever route the user provides in the $params array, or to the current page if no redirect is provided, as in the example above.

Any suggestions as to why it is doing this, as well as any solutions, would be great.

Thanks!


EDIT:

Here is a really brief overview of why I have taken the above approach, which might help with understanding the problem:

A requirement of the project is that the developers that will eventually use the cms can create a indefinite amount of pages via the cms control panel by clicking an "Add page" button. The idea is that we aren't writing new page controllers for every new page we want to create. With that I mind I have the following route:

Route::any('{page_slug}/page', array('as' => 'frontend.page', 'uses' => 'FrontendPagesController@display_page'))->where('page_slug',  '[-A-Za-z0-9_-]+');

The display_page function slimmed greatly is:

public function display_page($slug)
{
    $page = PagesModel::getPageBySlug($slug);
    return View::make($page['view_name']);
}

With this users can create a page with the click of a button, give it a name and a slug, and the app can then display that page and the corresponding view -- defined when creating the page -- without having to add any new routes, controllers etc.

The problem arrises in a situation where a user wants to include a contact form with a page. How do we know if they will add a form or not, what fields they will use and what validation it will require? I need a way of being able to add a completely custom contact form into any page without the developer having to touch touch the cms code. My solution to this was the approach given above: the developer drops the tag into the view and passes the function some params, which customise the forms functionality.

The Contact::form() function is kind of like a controller for the form. It gets and returns the view that contains the from html, processes the submission and returns success/errors messages depending on the outcome.

Now I don't necessarily need to use the approach above but I need a way of separating the contact form controller from the page controller and for developers to be able to add a form to any page without touching the cms backend code.

Any ideas on this would be great.

Answer

The Alpha picture The Alpha · Sep 17, 2013

You should call the redirect from a controller instead of doing it from the view. This is happening because, you are already in the view and it's visible, so if you somehow could make it (the body) hidden then it won't be visible before redirect happens.

But, you are doing it wrong and anti-pattern, IMO. Use the controller to make decision, view should be used only for presentation. This is the very basic rule in an MVC framework.