Внедрение (нечистых) унаследованных функций в область действия контроллеров Symfony - PullRequest
1 голос
/ 08 октября 2019

Устаревший проект

Я переписываю устаревшее PHP-приложение для использования Symfony. Первый имеет в своей основе около 400 функций в lib, которые все живут в глобальном масштабе. Структура проекта выглядит (очень упрощенно) следующим образом:

├── 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 в composer.json
  • , создать службу Symfony OldFunctionsService, включить файлы в ее конструктор изатем добавьте службу зависимости в контроллеры, где мне нужны старые функции в области видимости.

Однако оба метода не работают для функций, которые используют глобальные переменные $config и $db_handle. Они приносят обе переменные только в область функций соответствующей функции / конструктора импорта, а не в глобальную область / область функций контроллера, из которых в конечном счете вызываются старые функции.

Итак, какие у меня есть варианты для выводастарые функции в область без использования (довольно некрасиво и негибко)

require_once("config/config.php");
require_once("lib/functions.php");

в каждом контроллере? Это также, похоже, имеет недостаток - всегда создавать новое соединение с базой данных, а это не то, что мне нужно.

Я думаю, $config может быть реорганизован в класс со статическими свойствами и $db_handle в класс со статическимметод getConnection, который всегда возвращал бы один и тот же объект соединения (singleton), но для этого потребовалось бы изменить совсем немного кода в унаследованном приложении, что не идеально ...

Есть мысли?

1 Ответ

2 голосов
/ 08 октября 2019

Возможно, я неправильно понимаю проблему, но я думаю, что вы делаете это более сложным, чем оно есть на самом деле. Приложение 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 /reeting.php и использует глобальный $ config. functions.php загружает config.php иreeting.php.

...