将(不纯净的)旧功能引入Symfony控制器的范围

时间:2019-10-08 12:54:06

标签: php symfony scope legacy-code

旧项目

我正在重写旧版PHP应用程序以使用Symfony。前者的核心是lib中约有400个功能,所有功能都位于全球范围内。项目结构看起来(以非常简化的方式)如下:

├── index.php
├── lib
│   ├── lib_foo.php
│   ├── lib_bar.php
│   └── functions.php
└── config
    └── config.php

当前所有功能都包含在文件中,供lib/functions.php的一个包含所使用,这些文件又包含lib中的所有其他文件。

# index.php
<?php
include_once("lib/functions.php");

echo greeting();
echo visitorCount();
# lib/functions.php
<?php
include_once("../config/config.php");
include_once("lib_foo.php");
include_once("lib_bar.php");
...
// a lot more includes to follow

$db_handle = mysqli_connect(
    $config["db_host"], 
    $config["db_user"], 
    $config["db_pass"]
);

lib中的函数虽然不是纯函数,但是可以访问全局配置数组$config(在config/config.php中定义)和共享数据库连接$db_handle(在functions.php

# lib/lib_foo.php
<?php

function greeting() 
{
    // We are reading from a global config array here
    global $config;

    return "Welcome to " . $config["sitename"];
}


function visitorCount() 
{
    // We are using a global database handle defined in functions.php here
    global $db_handle;

    return mysqli_query($db_handle, "SELECT `visitor_count` FROM `visitors`");    
}

在新的Symfony应用程序中,除lib中的功能外,几乎所有东西都在被重写(目前太费力了……)。这些功能需要使新的Symfony控制器可以访问。 由于旧应用程序是同时扩展的,因此一个目标是在lib中重用代码,并进行尽可能少的修改。

我尝试/想要的东西

那么如何将这些功能引入Symfony中呢?我最初是想:

  • files的{​​{1}}属性中指定相应的文件
  • 创建一个Symfony服务composer.json,将文件包含在其构造函数中,然后将服务依赖注入到需要使用作用域中的旧功能的控制器中。

但是,这两种方法对于使用全局OldFunctionsService$config变量的函数均无效。它们只会将两个变量带入各自导入函数/构造函数的函数范围,而不带入最终调用旧函数的控制器函数的全局范围/范围。

那么在不使用(相当丑陋和不灵活)的情况下将旧功能纳入范围的我有哪些选择

$db_handle

在每个控制器中?似乎总是要创建新的数据库连接,而这并不是我想要的。

我猜想require_once("config/config.php"); require_once("lib/functions.php"); 可以重构为具有静态属性的类,而$config可以重构为具有静态方法$db_handle的类,该方法总是返回相同的连接对象(单个),但是将需要在旧版应用程序中更改大量代码,这是不理想的...

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

我可能会误解这个问题,但是我认为您正在使这一过程变得比实际复杂。 Symfony应用程序有两个主要入口点:public / index.php和bin / console。您真正需要做的就是在这两个文件中包含您的functions.php

# bin/console
#!/usr/bin/env php
<?php

use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;

if (false === in_array(\PHP_SAPI, ['cli', 'phpdbg', 'embed'], true)) {
    echo 'Warning: The console should be invoked via the CLI version of PHP, not the '.\PHP_SAPI.' SAPI'.\PHP_EOL;
}

set_time_limit(0);

require dirname(__DIR__).'/vendor/autoload.php';
require dirname(__DIR__).'/lib/functions.php'; // *** Just add this

我做了一个简单的命令只是为了检查:

class MyCommand extends Command
{
    protected static $defaultName = 'app:hello';

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->writeln(greeting());
    }
}

一切似乎都按预期进行。问候函数在lib / greeting.php中定义,并使用全局$ config。 functions.php会加载config.php和greeting.php。