Ожидаемый класс композитора (но не найден) при попытке автозагрузить PHP-файл

#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.php

3. Дэниел, я согласен. У меня есть все это в сервисе. Я пишу инструмент тестирования для 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. Пожалуйста, добавьте некоторые пояснения к вашему ответу, чтобы другие могли извлечь из него уроки. Имейте в виду, что этому вопросу почти год, и он уже содержит принятый ответ