Может войдёшь?
Черновики Написать статью Профиль

Возвращаем Route::controller() в Laravel 5.3 и выше

laravel php controllers routing

Как вы знаете, PHPRoute::controller() был удален из Laravel 5.3 и выше.

Лично мне листать файл роута на 3 страницы, выискивая что на что ссылается не доставляет никакого удовольствия. Да, есть PHPRoute::resource(), но хочется как в старое доброе время, прописал и забыл.

Короче, ниже класс для возвращения этого функционала.

PHP
<?php
namespace App\Classes;

class 
FRoute {

  private static 
$methodNameAtStartOfStringPattern = null;

  private static 
$httpMethods = [
    
'get',
    
'post',
    
'any',
    
'put',
    
'patch',
    
'delete',
  ];


  public static function 
controller($path, $controllerClassName)
  {
    
$class = new \ReflectionClass(app()->getNamespace().'Http\Controllers\\'.$controllerClassName);

    
$routes = [];

    
$publicMethods = $class->getMethods(\ReflectionMethod::IS_PUBLIC);

    
$methods = [];

    foreach (
$publicMethods as $method)
    {
      if (
$method->name == 'getMiddleware')
      {
        continue;
      }

      
$method->slug = self::slug($method);
      
$methods[] = $method;
    }

    
usort($methods, function ($a, $b)
    {
      
$aHasParam = false !== strpos($a->slug, '{');
      
$bHasParam = false !== strpos($b->slug, '{');

      if (!
$aHasParam && $bHasParam)
      {
        return -
1;
      }
      if (!
$bHasParam && $aHasParam)
      {
        return 
1;
      }

      return (
strcmp($a->slug, $b->slug));
    });

    foreach (
$methods as $method)
    {
      
$slug = $method->slug;
      
$methodName = $method->name;

      
$httpMethod = null;
      foreach (
self::$httpMethods as $httpMethod)
      {
        if (
self::stringStartsWith($methodName, $httpMethod))
        {
          \
Route::$httpMethod($path.'/'.$slug, $controllerClassName.'@'.$methodName);

          
$route = new \stdClass();
          
$route->httpMethod = $httpMethod;
          
$route->prefix = sprintf("Route::%-4s('%s',", $httpMethod, $path.'/'.$slug);
          
$route->target = $controllerClassName.'@'.$methodName;
          
$routes[] = $route;
          break;
        }
      }
    }
  }


  protected static function 
slug($method)
  {
    if (!
self::$methodNameAtStartOfStringPattern)
    {
      
self::$methodNameAtStartOfStringPattern = '/^('.implode('|', self::$httpMethods).')/';
    }

    
$cleaned = preg_replace(self::$methodNameAtStartOfStringPattern, '', $method->name);
    
$snaked = \Illuminate\Support\Str::snake($cleaned, ' ');
    
$slug = str_slug($snaked, '-');

    if (
$slug == "index")
    {
      
$slug = "";
    }

    foreach (
$method->getParameters() as $parameter)
    {
      if (
self::hasType($parameter))
      {
        continue;
      }
      
$slug .= sprintf('/{%s%s}', strtolower($parameter->getName()), $parameter->isDefaultValueAvailable() ? '?' : '');
    }

    if (
$slug != null && $slug[0] == '/')
    {
      return 
substr($slug, 1);
    }

    return 
$slug;
  }


  protected static function 
stringStartsWith($string, $match)
  {
    return (
substr($string, 0, strlen($match)) == $match) ? true : false;
  }


  protected static function 
hasType(\ReflectionParameter $param)
  {
    
preg_match('/\[\s\<\w+?>\s([\w]+)/s', $param->__toString(), $matches);

    return isset(
$matches[1]) ? true : false;
  }

}

Как этим пользоваться?

  1. Кидаем в папку app/classes файл с названием FRoute.php, вставляем в него код, который выше.
  2. Добавляем псевдоним в config/app.php
PHP
    'aliases' => [
        
//
    
'FRoute' => App\Classes\FRoute::class,
    ],
  1. Все, можно регистрировать контроллеры.
PHP
<?php
// /routes/web.php
FRoute::controller('/', 'PublicController');
FRoute::controller('admin', 'AdminController');
FRoute::controller('admin/users', 'Admin\UserController');
FRoute::controller('auth', 'AuthController');

Данный класс никак не влияет на контроллеры, DI в них, команды Artisan и тд, все будет работать как обычно.

Как вы считаете, полезен ли этот материал? Да Нет

Комментарии (1)

blackdark20

Ништяк все работает

P/s жаль не работают параметры FRoute::controller('/pages','PagesController',['getCreate' => 'pages.create']);

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.