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

徘徊边缘 提交于 2020-01-02 07:45:27

问题


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' => 'myemail@mydomain.com',
            '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.


回答1:


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.




回答2:


When you call a function in the view, it should return HTML which is then displayed. For instance, when you call {{ Url::to('foo') }} it generates http://yoursite.tld/foo.

When you call {{Contact::form(...)}}, it should output HTML. When you return View::make(...), you're returning HTML. When you return Redirect::to(...), you're returning a Laravel object which the Laravel router parses into a redirect header.

Redirects pretty much have to be called either by Route objects or by controllers. If you have your form submission handled by a controller, put your redirect there.




回答3:


Just got this very same problem, downgraded to "4.0.*" and it's fixed.

Looks like this is a 4.1.x problem.

Steps to downgrade

Change composer.json to:

"require": {
    ...
    "laravel/framework": "4.0.x",
    ...
}

edit app.php - 'Controller' alias

'Controller'      => 'Illuminate\Routing\Controller',

Should become

'Controller'      => 'Illuminate\Routing\Controllers\Controller',

And I had to remove those service providers

'Illuminate\Remote\RemoteServiceProvider',
'Illuminate\Exception\LiveServiceProvider',

EDIT:

I've opened an issue about this on Github and earlier Taylor fixed it. Do a composer update and you should be fine.




回答4:


The simple way:

header('Location: '.route('clients.create'));


来源:https://stackoverflow.com/questions/18846035/laravel-calling-redirectto-from-within-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!