【问题标题】:Laravel: is it possible to set a controller dynamically for a route?Laravel:是否可以为路由动态设置控制器?
【发布时间】:2015-06-14 04:54:57
【问题描述】:

所以,假设我确实有一个简单的控制器来处理书籍。

App\Http\Controllers\SimpleBooksController

routes.php里面我为它注册了一条路由:

Route::get('books/{id}','SimpleBooksController@doSimpleStuff');

但书的世界并不是那么简单。所以我想要另一个控制器来处理非常复杂的书籍内容。

在我的脑海中,我想像这样的东西会非常有用:

class ComplexBooksController extends SimpleBooksController

这样子类没有显式处理的路由回退到父类。

现在假设每本书都知道它是否复杂:$book->isComplex

而我想做的就是这样的

if (!$book->isComplex) {
    // route 'books/{id}' to SimpleBooksController@doSimpleStuff
} else {
    // route 'books/{id}' to ComplexBooksController@doComplexStuff
}

那么,如何才能做到这一点呢?

* 编辑 *

我目前处理这个问题的方式是在 routes.php 中静态设置控制器,但让它们监听参数化路由:

Route::get('books/simple/{id}', 'SimpleBooksController@doSimpleStuff');
Route::get('books/complex/{id}', 'ComplexBooksController@doComplexStuff');

【问题讨论】:

    标签: php routing laravel-5


    【解决方案1】:

    根据responses documentation,您应该能够使用匿名函数并将重定向返回到正确的控制器。

    这假设您在带有isComplex 的书籍表中拥有数据:

    Route::get('books/{id}', function($id) {
    
        $result = DB::select('SELECT is_complex FROM books WHERE id = ?', [$id]);
    
        if (empty($result)) abort(404);
    
        $book = $result[0];
    
        if ($book->is_complex)
            return redirect()->action('SimpleBooksController@doSimpleStuff');
        else
            return redirect()->action('ComplexBooksController@doComplexStuff');
    
    });
    

    【讨论】:

    • 请注意,这将是两个独立的请求。
    • 太好了,这正是我认为 laravel 应该可以实现的。但是存在一个问题,如果我有多个遵循这种模式的路由,我必须使用基本相同的代码多次编写这个匿名函数。只有控制器内部的动作会改变。那么也许还有另一种方法可以解决这个问题?也许使用中间件? (我现在只使用 laravel 1 周,请原谅我的幼稚)。
    【解决方案2】:

    您以错误的方式处理此问题。您不应该尝试使用不同的控制器和路由来处理它。

    书籍的路径应该是相同的 - 与书籍无关。

    然后,您的控制器会确定这本书是简单还是复杂 - 并调用适当的命令来处理。

    路线:

    Route::get('books/{id}','BooksController@doSimpleStuff');
    

    控制器:

    class BooksController extends Controller
    {
          public function showBook($book)
          {
               if ($book->isComplex()) {
                    $this->dispatch(new HandleComplexBook($book));
               } else {
                    $this->dispatch(new HandleSimpleBook($book));
               }
          }
    
    }
    

    那么你只有两个命令——一个用于简单书籍,一个用于复杂书籍

    class HandleComplexBook extends Command implements SelfHandling {
    
        protected $book;
    
        public function __construct(Book $book)
        {
            $this->book = $book;
        }
    
        public function handle()
        {
            // Handle the logic for a complex book here
        }
    
    }
    
    class HandleSimpleBook extends Command implements SelfHandling {
    
        protected $book;
    
        public function __construct(Book $book)
        {
            $this->book = $book;
        }
    
        public function handle()
        {
            // Handle the logic for a simple book here
        }
    
    }
    

    【讨论】:

    • 我不太相信这是我的应用程序要走的路。主要是因为我不担心“幕后”的处理——你可以创建一本书,你可以查看一本书,也许你可以买一本书。无论我是在处理一本复杂的书还是一本简单的书,这都是相同的代码。
    • *** 这是我要为复杂书籍升级的用户界面。也许通过 ajax 或其他方式提取一些额外的书籍数据。复杂书有一个“丰富的”用户界面。因此,将 SimpleController 描述为 DefaultController 并将 ComplexController 描述为 CustomController 可能更好。 DefaultController 足以满足 95% 的需求,而 CustomController 处理这些特殊情况。
    猜你喜欢
    • 2017-10-17
    • 2015-12-28
    • 2021-04-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2014-04-21
    • 2013-06-21
    相关资源
    最近更新 更多