Компоненты: перезагрузка

Не знаю, такую-ли ситуацию имел в виду BorisPlus в своем комментарии. Ну, чем богаты. Вообще не хотел это все описывать, потому как код довольно халтурно написан.

Этот код приложения, изначально крутившийся по Cake 1.1, был переписан для какой-то беты Cake 1.2. С текущей версией, 1.2.5, он работает без проблем, но, возможно, нуждается в чистке.

Эта часть программы выполняющий импорт данных от поставщиков. Поставщики предоставляют данные в CSV формате, но порядок колонок, некоторые значения и т.д., конечно разные. Для осмысленной обработки эти полученные данные надо привести к единообразному виду.

Данные поступают из написанного куцего Datasource, скармливанются компоненту, который и выполняет разбор и приведение к общему виду, потом записываются в нашу таблицу.

Компонент подгружается динамически, в зависимости от поставщика. Все компоненты являются наследниками базового и реализуют метод parse. Этот метод базового компонента, если не перегружен, возвращает NULL — в этом случае в нашу таблицу ничего не записываем, переходим к следующей порции данных. Соответственно методы наследников тоже могут возвращать NULL при ошибке разбора, например, при отсутствии какого-либо ключевого поля.

Еще базовый компонент содержит некоторое количество служебных методов, общих для всех, с целью унифицировать данные.

Увы, все файлы с компонентами находятся в каталоге components. Зато после перегрузки можно к загруженному компоненту обращаться по имени базового:

В коде контроллера загружается базовый компонент. Так как он нужен только в одном методе контроллера, в нем я его и загружаю:

Еще у базового компонента есть метод factory. Я не помню, почему я его статическим объявил, честно. :-) Он получает в качестве параметра ссылку на контроллер и название компонента для обработки данных от конкретного поставщика:

Теперь методы базового компонента, SupplierCsvComponent:

ну и код метода startup дочерних классов:

Решение неидельное, наверняка можно соптимизировать. Мне, честно говоря, заниматься этим не хочется. Просто потому, что я в итоге начну вообще все с нуля переделывать и менять логику. :)

Откровенно говоря, огород можно было бы и не городить. Можно через App::import() загрузить класс компонента, а потом какой-нибудь переменной контроллера присвоить экземпляр этого класса.

Наверное, я раньше грузил компонент, указывая его в массиве $components, потому и сделал такую навернутую схему.

А может мне не хотелось require_once использовать… Ну не помню. :)

Update: Если соберусь переписывать, надо будет рефлексию попробовать использовать. :)

Автор

Сергей Родовниченко

Родился, учился, работал и все такое. Занимаюсь поддержкой сайтов на Shop-Script, Joomla, Wordpress, Prestashop. А также на самописных движках на базе CakePHP.

8 thoughts on “Компоненты: перезагрузка”

  1. Да, я именно и пользовался App::import, только еще передавал параметр в ассоциированном массиве
    App::import(‘Component’, ‘SomeName’, array(‘file’ => ‘dir’.DS.’some.name.php’)), что мне и должно было позволить работать c классами в подпапке dir папки components. Но почему-то не выходило. Надо было попробовать еще поковырять, но времени не было. Задача идентична вашей. Есть абстрактный классс загрузки данных — некий адаптор Компонент, им объявляется исходный загрузчик, а во время исполнения уже определяется конкретный класс-загрузчик. Это позволило мне избавиться от дублирования кода и в нектором смысле разделить логику. Да, и стараясь делать все в терминах и договоренностях по именованию CakePHP, я также пользуюсь Inflector::camelize и т.п. На данный момент осталось решить только проблему с наличием require_once — и все будет в Cake «понятиях». В скором времени, думаю, этим заняться.

    1. Надо вынести все эти компоненты в отдельный плагин и грузить их App::import(‘Component’, ‘PluginName.ComponentName); :-)

  2. Да, я именно и пользовался App::import, только еще передавал параметр в ассоциированном массиве
    App::import(‘Component’, ‘SomeName’, array(‘file’ => ‘dir’.DS.’some.name.php’)), что мне и должно было позволить работать c классами в подпапке dir папки components. Но почему-то не выходило. Надо было попробовать еще поковырять, но времени не было. Задача идентична вашей. Есть абстрактный классс загрузки данных — некий адаптор Компонент, им объявляется исходный загрузчик, а во время исполнения уже определяется конкретный класс-загрузчик. Это позволило мне избавиться от дублирования кода и в нектором смысле разделить логику. Да, и стараясь делать все в терминах и договоренностях по именованию CakePHP, я также пользуюсь Inflector::camelize и т.п. На данный момент осталось решить только проблему с наличием require_once — и все будет в Cake «понятиях». В скором времени, думаю, этим заняться.

    1. Надо вынести все эти компоненты в отдельный плагин и грузить их App::import(‘Component’, ‘PluginName.ComponentName); :-)

  3. Cегодня после очередного рефакторинга вернулся к строке с require_once и просто заменил на необходимый App::import(’File’, ‘SomeName’, array(’file’ => ‘dir’.DS.’some.name.php’)) — все пашет. Не знаю, что ж у меня не хляло раньше)

  4. Cегодня после очередного рефакторинга вернулся к строке с require_once и просто заменил на необходимый App::import(’File’, ‘SomeName’, array(’file’ => ‘dir’.DS.’some.name.php’)) — все пашет. Не знаю, что ж у меня не хляло раньше)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *