Laravel Создание динамических маршрутов к контроллерам из базы данных Mysql

У меня есть следующая таблица: group_pages в базе данных MySQL с именем страницы имя маршрута:

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

что я пытаюсь сделать, это создать динамические маршруты в моем: rout.php?

Где, если я пойду к примеру: /about это пойдет в AboutController.php (который будет создан динамически) это возможно? Можно ли создать файл динамического контроллера?

Я пытаюсь создать динамические страницы маршрутов, которые ссылаются на контроллер

Пример, который я хочу генерировать это динамически в моем routes.php

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

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

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

6 ответов

Решение

Это неправильный способ создания динамических страниц, вы должны использовать базу данных и хранить все страницы в базе данных. Например:

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

Затем создайте PageEloquent модель:

class Page extends Eloquent {
    // ...
}

Затем создайте Controller за CRUD, вы можете использовать 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

Это грубая идея, попробуйте реализовать что-то вроде этого.

Потратив 2 часа, копаясь в источниках Google и Laravel, я пришел к этому решению, которое, я думаю, работает лучше всего и выглядит самым чистым. Нет необходимости в перенаправлениях и множественных внутренних запросах.

Вы добавляете этот маршрут в самом низу файлов маршрутов. Если никакие другие маршруты не совпадают, это выполняется. В закрытии вы решаете, какой контроллер и какое действие выполнить. Самое приятное то, что все параметры маршрута передаются в действие, а внедрение метода все еще работает. Линия ControllerDispatcer относится к классу Laravel Route(r?).

Мой пример будет обрабатывать 2 случая - сначала проверяет, существует ли пользователь с таким именем, а затем проверяет, может ли статья быть найдена слагом.

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

Надеюсь это поможет!

Пытаться

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

Таким образом мы можем построить динамический маршрут

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

Доступен компонент, который можно использовать для хранения маршрутов в базе данных. В качестве дополнительного преимущества этот компонент загружает только текущий активный маршрут, поэтому он повышает производительность, поскольку не все маршруты загружаются в память.

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

Следуйте инструкциям по установке, приведенным в файле readme.

Хранение маршрутов в базе данных

Единственное, что здесь нужно, - это ввести 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')
        );
    }
}

Выполняйте эту команду cli каждые 2–5 минут или после изменения данных, чтобы убедиться, что маршруты актуальны.

Зарегистрируйте RouteMiddleware в App\Http\Kernel.php

\Douma\Routes\Middleware\RouteMiddleware::class

Очистите свой web.php

Если вы определили какой-либо маршрут Laravel, обязательно очистите этот файл.

Использование маршрутов из базы данных

Вы можете использовать маршрут в лезвии:

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

Или вы можете ввести RouteManager-интерфейс где угодно, чтобы получить маршрут:

use Douma\Routes\Contracts\RouteManager;
class MyClass
{
    public function __construct(RouteManager $routeManager) 
    {
        $this->routeManager = $routeManager;
    }

    public function index()
    {
        echo $this->routeManager->routeByName('myroute')->url();
    }
}

Для получения дополнительной информации см. Файл readme.

Вы можете сделать что-то подобное. Это работает идеально для меня

      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');
    });
});
Другие вопросы по тегам