Symfony 4 LegacyRouteLoader 和 LegacyController

Symfony 4 LegacyRouteLoader and LegacyController

我正在尝试实现 Symfony 文档中列出的 LegacyController https://symfony.com/doc/current/migration.html#legacy-route-loader

为服务和路由使用自定义加载器配置: https://symfony.com/doc/current/routing/custom_route_loader.html#creating-a-custom-loader

我希望某处列出了一个完整的工作示例。

当我尝试 运行 debug:router 或 composer:install 时,我只是收到一个错误。这是在此初始配置上尝试各种细微变化之后。

$ console debug:router

In FileLoader.php line 166:

  Invalid service id: "App\Legacy\LegacyRouteLoader\" in /var/www/site/config/services.yaml (which is loaded in resource "/var/www/site/config/services.yaml").                                                        


In ContainerBuilder.php line 991:

  Invalid service id: "App\Legacy\LegacyRouteLoader\"  

--

<?php

// src/Legacy/LegacyRouteLoader.php
namespace App\Legacy;

use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

class LegacyRouteLoader extends Loader
{

    public function supports($resource, $type = null)
    {
        return 'extra' === $type;
    }

    public function load($resource, $type = null)
    {
        $collection = new RouteCollection();
        $finder = new Finder();
        $finder->files()->name('*.php');

        /** @var SplFileInfo $legacyScriptFile */
        foreach ($finder->in($this->webDir) as $legacyScriptFile) {
            // This assumes all legacy files use ".php" as extension
            $filename = basename($legacyScriptFile->getRelativePathname(), '.php');
            $routeName = sprintf('app.legacy.%s', str_replace('/', '__', $filename));

            $collection->add($routeName, new Route($legacyScriptFile->getRelativePathname(), [
                '_controller' => 'App\Controller\LegacyController::loadLegacyScript',
                'requestPath' => '/' . $legacyScriptFile->getRelativePathname(),
                'legacyScript' => $legacyScriptFile->getPathname(),
            ]));
        }

        return $collection;
    }
}

--

<?php

// src/Controller/LegacyController.php
namespace App\Controller;

use Symfony\Component\HttpFoundation\StreamedResponse;

class LegacyController
{
    public function loadLegacyScript(string $requestPath, string $legacyScript)
    {
        return StreamedResponse::create(
            function () use ($requestPath, $legacyScript) {
                $_SERVER['PHP_SELF'] = $requestPath;
                $_SERVER['SCRIPT_NAME'] = $requestPath;
                $_SERVER['SCRIPT_FILENAME'] = $legacyScript;

                chdir(dirname($legacyScript));

                include $legacyScript;
            }
        );
    }
}

--

# config/services.yaml

# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:

services:
  # default configuration for services in *this* file
  _defaults:
    autowire: true      # Automatically injects dependencies in your services.
    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

  # makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  App\:
    resource: '../src/*'
    exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

  # controllers are imported separately to make sure services can be injected
  # as action arguments even if you don't extend any base controller class
  App\Controller\:
    resource: '../src/Controller'
    tags: ['controller.service_arguments']

  # add more service definitions when explicit configuration is needed
  # please note that last definitions always *replace* previous ones

  App\Legacy\LegacyRouteLoader\:
    tags: ['routing.loader']

--

# config/routes.yaml
#index:
#    path: /
#    controller: App\Controller\DefaultController::index

app_legacy:
  resource: .
  type: extra

感谢上面的 @cerad,我设法通过一些更改让它继续运行。

# config/services.yaml

# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:

services:
  # default configuration for services in *this* file
  _defaults:
    autowire: true      # Automatically injects dependencies in your services.
    autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.

  # makes classes in src/ available to be used as services
  # this creates a service per class whose id is the fully-qualified class name
  App\:
    resource: '../src/*'
    exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

  # controllers are imported separately to make sure services can be injected
  # as action arguments even if you don't extend any base controller class
  App\Controller\:
    resource: '../src/Controller'
    tags: ['controller.service_arguments']

  # add more service definitions when explicit configuration is needed
  # please note that last definitions always *replace* previous ones

  App\Legacy\LegacyRouteLoader:
    tags: ['routing.loader']

--

<?php

// src/Legacy/LegacyRouteLoader.php
namespace App\Legacy;

use Symfony\Component\Config\Loader\Loader;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;

class LegacyRouteLoader extends Loader
{

    private $webDir = __DIR__.'/../../public/';

    public function supports($resource, $type = null)
    {
        return 'extra' === $type;
    }

    public function load($resource, $type = null)
    {
        $collection = new RouteCollection();
        $finder = new Finder();
        $finder->files()->name('*.php');

        /** @var SplFileInfo $legacyScriptFile */
        foreach ($finder->in($this->webDir) as $legacyScriptFile) {
            // This assumes all legacy files use ".php" as extension
            $filename = basename($legacyScriptFile->getRelativePathname(), '.php');
            $routeName = sprintf('app.legacy.%s', str_replace('/', '__', $filename));

            $collection->add($routeName, new Route($legacyScriptFile->getRelativePathname(), [
                '_controller' => 'App\Controller\LegacyController::loadLegacyScript',
                'requestPath' => '/' . $legacyScriptFile->getRelativePathname(),
                'legacyScript' => $legacyScriptFile->getPathname(),
            ]));
        }

        return $collection;
    }
}