【问题标题】:Laravel Creating Dynamic Routes to controllers from Mysql databaseLaravel 从 Mysql 数据库创建到控制器的动态路由
【发布时间】:2014-06-02 10:32:37
【问题描述】:

我有下表:mysql 数据库中的 group_pages 页面名称路由名称:

   id   name      route
  --------------------
    0   About      about
    1   Contact    contact
    2   Blog       blog

我要做的是在我的 : routes.php 中创建动态路由?

如果我去哪里,例如:/about,它将去AboutController.php(将动态创建)这可能吗?是否可以创建动态控制器文件?

我正在尝试创建链接到控制器的动态页面路由

示例我想在我的routes.php 中动态生成它

Route::controller('about', 'AboutController');

Route::controller('contact', 'ContactController');

Route::controller('blog', 'BlogController');

【问题讨论】:

  • 但是为什么呢?无论如何,您都必须编写控制器才能完成工作,那么您为什么不想只在代码中编写路由,而不是增加数据库的工作量呢? “动态创建”控制器是什么意思?
  • 我正在尝试创建动态页面?在管理员中我可以添加这些页面的位置 - 名称,我需要这样做,以便我可以为用户分配权限以访问他们在登录时可以查看的页面
  • 是否可以动态添加这些控制器,或者我必须进入我的 routes.php 并一一添加这些控制器?
  • 但是所有这些页面都将只有一些内容(文本、图像)没有形式和东西?
  • 那是什么让这变得困难,它混合了文本内容和表单等,例如,如果用户登录并且他去 /about(如果他有权限)那么他可以访问下的所有页面目录 /about ,如 /about/index 、 /about/page2 等。

标签: php laravel laravel-4


【解决方案1】:

这不是创建动态页面的正确方法,您应该使用数据库并将所有页面保存在数据库中。例如:

// Create pages table for dynamic pages
id | slug | title | page_content 

然后创建PageEloquent模型:

class Page extends Eloquent {
    // ...
}

然后为CRUD创建Controller,你可以使用resource控制器或普通控制器,例如,通常是PageController

class PageController extends BaseController {

    // Add methods to add, edit, delete and show pages

    // create method to create new pages
    // submit the form to this method
    public function create()
    {
        $inputs = Input::all();
        $page = Page::create(array(...));
    }

    // Show a page by slug
    public function show($slug = 'home')
    {
        $page = page::whereSlug($slug)->first();
        return View::make('pages.index')->with('page', $page);
    }
}

views/page/index.blade.php 查看文件:

@extends('layouts.master')
{{-- Add other parts, i.e. menu --}}
@section('content')
    {{ $page->page_content }}
@stop

要显示页面,请创建这样的路由:

// could be page/{slug} or only slug
Route::get('/{slug}', array('as' => 'page.show', 'uses' => 'PageController@show'));

要访问页面,您可能需要url/link,如下所示:

http://example.com/home
http://example.com/about

这是一个粗略的想法,尝试实现这样的东西。

【讨论】:

  • 谢谢,slug是什么意思,是目录名比如“/about”吗?
  • 它是数据库中的标识符,例如about将是通过slug字段识别数据库中的about页面的slug。
  • 但是对于路线我需要从'page/{slug}'开始吗?我们可以只做'{slug}'
  • 是的,你可以使用{page}
  • @TheAlpha 非常感谢这位伙伴,帮了我很多忙!
【解决方案2】:

花了 2 个小时,在 google 和 Laravel 源代码中挖掘后,我想出了这个解决方案,我认为它效果最好,看起来最干净。无需重定向和多个内部请求。

您将此路由添加到路由文件的最底部。 如果没有其他路由匹配,则执行此操作。在闭包中,您决定执行哪个控制器和操作。 最好的部分是 - 所有路由参数都传递给操作,并且方法注入仍然有效。 ControllerDispatcer 行来自 Laravel Route(r?) 类。

我的示例将处理 2 种情况 - 首先检查用户是否以该名称存在,然后检查是否可以通过 slug 找到文章。

Laravel 5.2(以下 5.3)

Route::get('{slug}/{slug2?}', function ($slug) {
    $class = false;
    $action = false;

    $user = UserModel::where('slug', $slug)->first();
    if ($user) {
        $class = UserController::class;
        $action = 'userProfile';
    }

    if (!$class) {
        $article= ArticleModel::where('slug', $slug)->first();
        if ($article) {
            $class = ArticleController::class;
            $action = 'index';
        }
    }

    if ($class) {
        $route = app(\Illuminate\Routing\Route::class);
        $request = app(\Illuminate\Http\Request::class);
        $router = app(\Illuminate\Routing\Router::class);
        $container = app(\Illuminate\Container\Container::class);
        return (new ControllerDispatcher($router, $container))->dispatch($route, $request, $class, $action);
    }

    // Some fallback to 404
    throw new NotFoundHttpException;
});

5.3 改变了控制器的调度方式。

这是我的 5.3、5.4

的动态控制器示例
namespace App\Http\Controllers;


use Illuminate\Routing\Controller;
use Illuminate\Routing\ControllerDispatcher;
use Illuminate\Routing\Route;

class DynamicRouteController extends Controller
{
    /**
     * This method handles dynamic routes when route can begin with a category or a user profile name.
     * /women/t-shirts vs /user-slug/product/something
     *
     * @param $slug1
     * @param null $slug2
     * @return mixed
     */
    public function handle($slug1, $slug2 = null)
    {
        $controller = DefaultController::class;
        $action = 'index';

        if ($slug1 == 'something') {
            $controller = SomeController::class;
            $action = 'myAction';
        }

        $container = app();
        $route = $container->make(Route::class);
        $controllerInstance = $container->make($controller);

        return (new ControllerDispatcher($container))->dispatch($route, $controllerInstance, $action);
    }
}

希望这会有所帮助!

【讨论】:

  • 我正在寻找相同的功能。任何适用于 laravel 5.7 的想法?
  • 它有效 :) 任何想法如何将参数传递给 'myAction' 方法?
  • 工作得很好,谢谢 - 唯一的问题是当它降落在第二个控制器上时必须重新运行相同的查询才能再次获取模型。有什么办法吗?
  • @anthonyroberts 您是在谈论方法参数中的模型绑定吗?您可能需要深入了解框架的内部结构,使用 xdebug 逐步了解并了解是否有办法避免它。
【解决方案3】:

试试

Route::get('/', ['as' => 'home', 'uses' => 'HomeController@index']);

$pages = 
Cache::remember('pages', 5, function() {
    return DB::table('pages')
            ->where('status', 1)
            ->lists('slug');

});

if(!empty($pages)) 
{
  foreach ($pages as $page)
  {
    Route::get('/{'.$page.'}', ['as' => $page, 'uses' => 'PagesController@show']);
   }
}

【讨论】:

    【解决方案4】:

    有一个可用的组件,您可以使用它在数据库中存储路线。作为一个额外的优势,这个组件只加载当前活动的路由,因此它提高了性能,因为并不是所有的路由都被加载到内存中。

    https://github.com/douma/laravel-database-routes

    按照自述文件中提供的安装说明进行操作。

    在数据库中存储路由

    这里唯一需要的是将RouteManager 注入到例如cli 命令中。使用addRoute 可以告诉RouteManager 将路由存储到数据库中。您可以轻松更改此代码并使用您自己的页面存储库或其他数据来构建路由。

    use Douma\Routes\Contracts\RouteManager;
    
    class RoutesGenerateCommand extends Command 
    {
        protected $signature = 'routes:generate';
        private $routeManager;
    
        public function __construct(RouteManager $routeManager)
        {
            $this->routeManager = $routeManager;
        }
    
        public function handle()
        {
            $this->routeManager->addRoute(
                new Route('/my-route', false, 'myroute', MyController::class, 'index')
            );
        }
    }
    

    每 2-5 分钟或在数据发生更改后运行此 cli 命令,以确保路由是最新的。

    在 App\Http\Kernel.php 中注册 RouteMiddleware

    \Douma\Routes\Middleware\RouteMiddleware::class

    清空你的 web.php

    如果你已经定义了任何 Laravel 路由,请确保清空这个文件。

    使用数据库中的路由

    你可以在blade中使用路由:

    {{ RouteManager::routeByName('myroute')->url() }}
    

    或者你可以在任何你想获取路由的地方注入RouteManager-interface:

    use Douma\Routes\Contracts\RouteManager;
    class MyClass
    {
        public function __construct(RouteManager $routeManager) 
        {
            $this->routeManager = $routeManager;
        }
    
        public function index()
        {
            echo $this->routeManager->routeByName('myroute')->url();
        }
    }
    

    有关详细信息,请参阅自述文件。

    【讨论】:

      【解决方案5】:

      我们可以通过这种方式制作动态路由

      // Instanciate a router class.
      $router = app()->make('router');
      

      从数据库中获取路由值

      // For route path this can come from your database.
      $paths = ['path_one','path_two','path_three'];
      

      然后迭代该值以制作动态路由

      // Then iterate the router "get" method.
      foreach($paths as $path){
          $router->resource($path, 'YourController');
      }
      

      您也可以使用 GET|POST|PUT|PATCH|DELETE 方法

      // Then iterate the router "get" method.
      foreach($paths as $path){
          $router->get($path, 'YourController@index')->name('yours.index');
      }
      

      【讨论】:

      • 除了这个答案没有考虑到 laravel 有一个路由缓存,所以每次在数据库中添加路由时你都需要手动刷新缓存
      【解决方案6】:

      你可以做这样的事情。它非常适合我

      use Illuminate\Container\Container;
      use Illuminate\Routing\ControllerDispatcher;
      use Illuminate\Support\Facades\Auth;
      use Illuminate\Support\Facades\Route;
      use Illuminate\Routing\Route as MainRoute;
      use Illuminate\Routing\Router;
      
      Route::group([
          'prefix'     => config('app.payment.route_prefix'),
          'namespace'  => config('app.payment.route_namespace'),
          'middleware' => config('app.payment.route_middleware')
      ], function (Router $router) {
      
          /**
           * Resolve target payment method controller
           *
           * @param $key Example key [paypal]
           * @param $action
           * @return mixed
           */
          $resolver = function ($key, $action) {
              $route = app(MainRoute::class);
              $container = app(Container::class);
      
              // Generate App\\Http\Controllers\PaymentMethods\PaypalController
              $controller = app(sprintf('%s\\%sController', config('app.payment.route_namespace'), ucfirst($key)));
      
              return (new ControllerDispatcher($container))->dispatch($route, $controller, $action);
          };
      
          $router->post('{key}/error', function ($key) use ($resolver) {
              return $resolver($key, 'error');
          });
      
          $router->post('{key}/success', function ($key) use ($resolver) {
              return $resolver($key, 'success');
          });
      
          $router->get('{key}', function ($key) use ($resolver) {
              return $resolver($key, 'index');
          });
      });
      

      【讨论】:

        猜你喜欢
        • 2023-03-05
        • 2017-10-17
        • 1970-01-01
        • 1970-01-01
        • 2014-04-21
        • 1970-01-01
        • 1970-01-01
        • 2014-08-26
        • 2016-07-21
        相关资源
        最近更新 更多