3

我目前正在开发一个基于 Laravel 4 框架的 cms。我正在尝试构建一个类似于 Pyro CMS 的插件系统,其中模块视图可以使用 Blade 模板系统包含在页面视图中。

我正在构建一个联系表单插件,如果提交成功,会将用户重定向到给定的 url,或者只是重定向回现有页面。

我的联系表单类的代码是:

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');
}

}

有一个页面控制器将根据使用的路由显示适当的页面视图,其想法是用户可以将联系表单放入任何页面模板并通过从模板视图中调用表单函数轻松自定义它,如下所示

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

        {{ Contact::form(array(

            'to' => 'myemail@mydomain.com',
            'view'  => 'contact_form_1',

        )) }}

    </body>
</html>

除了重定向之外,这一切都很好。当表单提交成功并且发送的消息页面刷新并显示以下消息代替联系表单

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.

大约 2 秒后,重定向发生,浏览器被重定向到用户在 $params 数组中提供的任何路由,或者如果没有提供重定向,则重定向到当前页面,如上例所示。

关于它为什么这样做的任何建议以及任何解决方案都会很棒。

谢谢!


编辑:

以下是我为什么采用上述方法的一个非常简短的概述,这可能有助于理解问题:

该项目的一个要求是最终将使用 cms 的开发人员可以通过 cms 控制面板单击“添加页面”按钮来创建无限数量的页面。这个想法是我们不会为我们想要创建的每个新页面编写新的页面控制器。有了这个我介意我有以下路线:

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

display_page大大瘦身的功能是:

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

有了这个,用户可以通过点击一个按钮来创建一个页面,给它一个名称和一个 slug,然后应用程序可以显示该页面和相应的视图——在创建页面时定义——而无需添加任何新的路由, 控制器等

问题出现在用户想要在页面中包含联系表单的情况下。我们如何知道他们是否会添加表单、他们将使用哪些字段以及需要哪些验证?我需要一种能够将完全自定义的联系表单添加到任何页面的方法,而无需开发人员触摸 cms 代码。我对此的解决方案是上面给出的方法:开发人员将标记放入视图中并传递函数一些参数,这些参数自定义表单功能。

Contact::form()函数有点像表单的控制器。它获取并返回包含 from html 的视图,处理提交并根据结果返回成功/错误消息。

现在我不一定需要使用上述方法,但我需要一种将联系表单控制器与页面控制器分开的方法,并且开发人员能够在不接触 cms 后端代码的情况下将表单添加到任何页面。

任何关于此的想法都会很棒。

4

4 回答 4

6

您应该redirect从控制器调用而不是从视图中调用。发生这种情况是因为,您已经在视图中并且它是可见的,因此如果您可以以某种方式使其(主体)隐藏,那么在重定向发生之前它将不可见。

但是,你做错了anti-pattern,IMO。使用控制器做出决定,视图应该仅用于演示。这是MVC框架中非常基本的规则。

于 2013-09-17T18:39:42.133 回答
1

当您在视图中调用函数时,它应该返回 HTML,然后显示。例如,当您调用{{ Url::to('foo') }}它时会生成http://yoursite.tld/foo

当你调用时{{Contact::form(...)}},它应该输出 HTML。当您返回时View::make(...),您将返回 HTML。当您返回时Redirect::to(...),您将返回一个 Laravel 对象,Laravel 路由器将其解析为重定向标头。

重定向几乎必须由 Route 对象或控制器调用。如果您的表单提交由控制器处理,请将重定向放在那里。

于 2013-09-17T18:08:56.323 回答
0

刚刚遇到同样的问题,降级到“4.0.*”并且它已修复。

看起来这是一个 4.1.x 问题。

降级步骤

将 composer.json 更改为:

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

编辑 app.php - 'Controller' 别名

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

应该成为

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

我不得不删除那些服务提供商

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

编辑:

我在 Github 上打开了一个关于这个的问题,早些时候 Taylor 修复了它。做一个作曲家更新,你应该没问题。

于 2013-09-20T17:41:00.340 回答
0

简单的方法:

header('Location: '.route('clients.create'));
于 2018-02-19T00:36:16.050 回答