Здравствуйте, не могу понять как работают сервис-провайдеры в Laravel. Мне нужно реализовать свой функционал для моего проекта. Допустим у меня есть такой функционал: PHP: interface FileSizeInterface { public function showFileSize(); } abstract class ParamHandler { protected $source; protected $params = []; public function __construct($source) { $this->source = $source; } public function addParam ($key, $value) { $this->params[$key] = $value; } public static function getInstance($filename) { if (preg_match("/\.xml$/i", $filename)) { return new XmlParamHandler($filename); } return new TextParamHandler($filename); } abstract function write(); abstract function read(); } class XmlParamHandler extends ParamHandler implements FileSizeInterface { function write() { // Запись в формате XML } function read() { // Чтение из XML файла } function showFileSize() { // Показать информацию } } class TextParamHandler extends ParamHandler implements FileSizeInterface { function write() { // Запись в текстовый файл } function read() { // Чтение из текстового файла } function showFileSize() { // Показать информацию } } Как все это запихнуть в сервис-контейнер? И вообще нужно ли его туда пихать если я могу все это положить в отдельную папку App и подключать файлы через use
@pr0n1x, нужно, чтоб отделить создание класса от использования. И чтоб он автоматически в контроллеры инъектился. Читай раздел Dependency Injection документации. А service provider как раз нужен, чтоб засунуть в контейнер все зависимости. В небольших проектах достаточно в AppServiceProvider, который при создании проекта появляется, запихнуть. Вот фрагмент из моего кода: PHP: <?php namespace App\Providers; use App\Observers\UserObserver; use App\Services\Login\FakeLoginCodeGenerator; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. * * @return void */ public function boot() { User::observe(UserObserver::class); } /** * Register any application services. * * @return void */ public function register() { $this->app->singleton(ILoginCodeGenerator::class, FakeLoginCodeGenerator::class); // ..... } } Реально там больше, я подсократил --- Добавлено --- Потом я в контроллере пишу PHP: class LoginController { function sendCode(ILoginCodeGenerator $codeGen) { } } И мне Laravel сам передаёт тот генератор, который я в контейнер положил, без моего участия
Зачем создавать экземпляры классов если их не использовать, чтобы они просто висели в контейнере? Мой класс должен отработать в методе контроллера, сгенерировать мне json и все. Почему предпочтительней запихнуть его в контейнер вместо того, чтобы подключить его через use и использовать там где мне нужно?
Контейнер не создаёт экземпляр, пока не попросишь. Причина - убрать создание зависимостей из кода класса, который их использует, не дублировать это создание, если класс нужен в нескольких местах, возможность подставлять разные реализации одного интерфейса. В моём случае, когда я закончу тестировать, я просто в провайдере заменю FakeLoginCodeGenerator на RealCodeGenerator, а контроллер трогать не понадобится. В общем, читаем про SOLID, инверсию зависимостей, паттерны и др. А ещё в некоторых случаях экземпляр требует более сложной инициализации, чем new ClassName, тогда писать это в контроллере - засорять свой код. Но, от себя, профит от таких вещей становится заметен на крупных проектах. Если проект мелкий, то ничего страшного, можно и прямо в контроллере создать зависимость. Просто со знанием, что так делать не хорошо, и в последствии может потребоваться отрефакторить.
Статьи хорошие, но практически со всем, что там написано я знаком, использую это в своих классах, но все равно я не монимаю, зачем и как это используется в ларавел.