#php #file #symfony #composer-php #autoload
#php #файл #symfony #composer-php #автозагрузка
Вопрос:
Я пытаюсь автоматически загрузить только PHP-файл без какого-либо класса в нем, но вместо этого со вспомогательными функциями. Что-то вроде помощников Laravel, поэтому:
<?php
if (!function_exists('fixture')) {
function fixture()
{
// some code here
}
}
Согласно документам, это довольно просто, я делаю что-то подобное:
"autoload": {
"files": [
"src/Helpers/helpers.php"
],
"psr-4": {
"App\": "src/"
}
},
После этого я делаю composer dumpautoload
, чтобы восстановить все это. Затем происходит странная вещь.
Если это имеет значение, я использую Symfony 5. Пока я храню свой вспомогательный файл в src
каталоге, я получаю эту ошибку:
Fatal error: Uncaught SymfonyComponentDependencyInjectionExceptionInvalidArgumentException: Expected to find class "AppHelpershelpers" in file "/srv/app/src/Helpers/helpers.php" while importing services from resource "../src/*", but it was not found! Check the namespace prefix used with the resource. in /srv/app/vendor/symfony/dependency-injection/Loader/FileLoader.php:206
Когда я перемещаю его за пределы каталога src, кажется, что он работает нормально. Мне кажется, что composer решает, что psr-4 важнее, чем ключ файла.
Что интересно, Laravel делает то же самое, и, по-видимому, работает просто отлично. Пример:
"autoload": {
"files": [
"src/Illuminate/Foundation/helpers.php",
"src/Illuminate/Support/helpers.php"
],
"psr-4": {
"Illuminate\": "src/Illuminate/"
}
},
У кого-нибудь есть идеи, почему это может происходить? Я уверен, что это что-то глупое, я просто не вижу, что это такое…
Комментарии:
1. Я знаю, что вы приняли приведенный ниже ответ, но эта конкретная ошибка исходит от компонента Symfony DI. Он пытается автоматически подключить ваш файл, думая, что там есть класс. Просто измените config / services. yaml и укажите исключить ваш helpers.php досье. Ничего общего с автозагрузкой.
2. @Cerad снова спасает 🙂 Я попробую это и сообщу вам, что произошло. Спасибо!
3. Ааааа И это сработало. Удивительные. Откуда вы знаете все эти вещи @_@?
4. Рад помочь. Я использую Symfony 2 с тех пор, как он был выпущен еще в 2012 году. Но, рискуя показаться язвительным, на 90% вопросов Symfony, которые я вижу, можно ответить, просто выполнив поиск в сообщении об ошибке. «Ожидается, что будет найден класс» — это пустая выдача.
5. Да, я видел это, но совершенно вылетело из головы, что в службах есть исключение. В наши дни я работаю в основном с Laravel и использую Symfony только для домашних проектов. Ну, в любом случае, еще раз спасибо. Я буду иметь это в виду.
Ответ №1:
Ваши настройки composer выглядят нормально, просто автозагрузчик Symfony с Service manager (di-container) загружается первым.
Вы вызываете функцию из пространства имен, сама функция не имеет пространства имен.
Попробуйте использовать fixture();
вместо того, чтобы просто fixture();
явно использовать корневое пространство имен.
Я не уверен, есть ли обходной путь, я просто предполагаю, что Symfony не настроил di-контейнер для обработки функции вместо класса.
Хорошим подходом было бы правильно подключить класс и не использовать его извне рабочего процесса проекта.
Учитывая тесты, есть простые способы настройки setUp()
и загрузки от поставщиков данных.
Чтобы загрузить что-то для всех тестов, используйте --bootstrap
флаг:
phpunit --bootstrap test/bootstrap.php
Затем bootstrap.php
:
<?php
require_once 'vendor/autoload.php';
function fixture() {
// ...
}
Комментарии:
1. Вероятно, это так. Проблема в том, что это происходит (я имею в виду ошибку) даже без вызова функции. Когда я пытаюсь запустить модуль PHP для выполнения фиктивного теста, он завершается с ошибкой еще до того, как он доберется до выполнения теста. Интересно, может быть, мне просто переместить его из папки src и дождаться исправления Symfony?
2. @Robert Mmmmmm лучше всего было бы создать класс и правильно подключить его, а не использовать внешнюю глобальную функцию. Или просто
require_once __DIR__ . /';
вспомогательный файл в вашем bootstrap.php3. Дэниел, я согласен. У меня есть все это в сервисе. Я пишу инструмент тестирования для Symfony, позволяющий легко генерировать фиктивные данные и легко тестировать API. Теперь эта служба уже доступна через пользовательский
ApiTestCase
, который расширяется каждым тестом, поэтому я могу получить к нему доступ$this->fixture()
следующим образом. Я просто хотел попробовать. Я надеялся, что у меня будетfixture()
помощник, чтобы он выглядел немного лучше. Внутри этого помощника я бы либо создал экземпляр этой службы, либо, возможно, просто вызвал для нее статический метод. Пока не уверен. В любом случае я мог бы отказаться от этой идеи, если это слишком сложно. Я думаю, что ваш ответ очень хорош4. @Robert пожалуйста, посмотрите мою правку, не помогает ли вам в этом случае какой-либо из стандартных методов phpunit?
5. Ах да, я только что это увидел. Я уже использую
setUp
иsetUpBeforeClass
для быстрого и легкого обновления базы данных во время тестов (для этого создана волшебная черта). Для генерации данных я используюnelmio/alice
bundle, который генерирует объекты с фиктивными данными, которые я затем могу сохранить в базе данных, если это имеет смысл, поэтому на этот раз я пропустил поставщиков данных. Я хотел бы иметь такие аккуратные и чистые оболочки, чтобы я мог добавлять помощников и улучшения. Весь дизайн работает нормально, это просто кусочки, которые я пытаюсь улучшить, это имеет смысл.
Ответ №2:
в config/services.yaml
App:
resource: '../src/'
exclude:
- '../src/helpers.php'
или
App:
resource: '../src/*'
exclude: '../src/{helpers.php}'
Комментарии:
1. Пожалуйста, добавьте некоторые пояснения к вашему ответу, чтобы другие могли извлечь из него уроки. Имейте в виду, что этому вопросу почти год, и он уже содержит принятый ответ