Preload компонента в модуле

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ответить
Аватара пользователя
Loki
Сообщения: 65
Зарегистрирован: 2011.01.16, 10:47
Откуда: Омск

Preload компонента в модуле

Сообщение Loki »

В Yii можно содавать модули, поэтому весь backend, я делаю в виде отдельного модуля – admin.
В текущем проекте для панели администратора используется – YiiBootstrap.
Конфигурация bootstrap находится в секции 'components', общего конфига(так как в некоторых виджетах используется вызов Yii::app()->bootstrap), а при конфигурации внутри 'components' непосредственно модуля – такой способ не работает.
Так вот, когда я пытаюсь сделать preload компонента bootstrap – он не работает, потому что preload модуля проверяет наличие конфигурации компонента в текущем модуле, и если конфига нет – пропускает его.

Ситуация получается следующая:
  • Я не могу конфигурировать компонент в модуле, потому что используется Yii::app()->bootstrap.
  • Я не могу сделать preload компонентов не сконфигурированных для модуля(в то время как глобально – он сконфигурирован).
  • Мне приходится использовать злое шаманство в виде Yii::app()->getComponent("bootstrap"); в init модуля.
Следовательно возникают вопросы:
  • Возможно стоит при пооиске конфигурации компонента мержить его конфиг из модуля с глобальным?
  • Возможно стоит сделать допустимым вызов компонентов текущего модуля через Yii::app()->%componentname%
Или это баг прежде всего YiiBotstrap? Но тогда как получить текущий модуль приолжения для вызова компонента из него(тоесть код аналогичный Yii::app()->bootstrap, но работающий с компонентом текущего модуля)?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Preload компонента в модуле

Сообщение samdark »

preload работает на уровне приложения, а не на уровне модуля. На то он и preload.
Аватара пользователя
Loki
Сообщения: 65
Зарегистрирован: 2011.01.16, 10:47
Откуда: Омск

Re: Preload компонента в модуле

Сообщение Loki »

Понял. Тогда для чего есть возможность задать его в конфиге модуля? Получается это не рекомендуемая к использованию возможность?
Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Preload компонента в модуле

Сообщение lancecoder »

да тут вообще нестыковок много в этой области, например уровень вложенности модулей не учитывается, к любому модулю можно достучаться не от родителя а от корня - app(). Любой компонент привязанный к модулю будет глобальным getComponent опять же от app().
Аватара пользователя
r3verser
Сообщения: 195
Зарегистрирован: 2012.04.01, 17:29
Откуда: Киев

Re: Preload компонента в модуле

Сообщение r3verser »

Кстати да, пару дней назад, тоже столкнулся с Yii Bootstrap и тоже захардкодил его вызов через getComponent. Штука в том, что он при инициализации добавляет меню в gii, со своими шаблонами, но также при этом он начинает загружать свои css/js, что рушит верстку на сайте. Поэтому было бы намного удобнее, указать в конфиге gii, preload => bootstrap, дабы не грузить его со всем сайтом. В доках вроде есть такая переменная http://www.yiiframework.com/doc/api/1.1 ... oad-detail , но пока не работает.
Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Preload компонента в модуле

Сообщение lancecoder »

было бы более логично, Yii::app()->getModule('front')->getModule('site'), и тогда можно было бы site иметь и в back, сейчас же надо заюзывать немспейсы, и вызов происходит от корня, что как по мне усложняет понимание кода. Опять же компоненты которые объявлены в модуле должны быть в модуле а не в приложении имхо, но это BC как говорится и не изменится.
upd: бред про неймспейсы, тут ключ в массиве конфига, но суть та же)
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Preload компонента в модуле

Сообщение samdark »

В 1.1 этого не сделать. Много всего поломает.
Аватара пользователя
creocoder
Сообщения: 138
Зарегистрирован: 2010.01.24, 05:29
Откуда: Тамбов

Re: Preload компонента в модуле

Сообщение creocoder »

preload работает на уровне приложения, а не на уровне модуля. На то он и preload.
Не совсем так. Приложение является main модулем, все модули которые определяются в конфигурации приложения являются nested по отношению к нему. Preload работает на уровне модуля, но только с теми компонентами, которые определены в конфигурации этого модуля. Что логично.
Так вот, когда я пытаюсь сделать preload компонента bootstrap – он не работает, потому что preload модуля проверяет наличие конфигурации компонента в текущем модуле, и если конфига нет – пропускает его.
И правильно делает что не работает. Например:

Код: Выделить всё

	// modules
	'modules'=>array(
		'test'=>array(
			'preload'=>array('testGlobal'),
		),
	),

	// application components
	'components'=>array(
		'testGlobal'=>array(
			'class'=>'TestGlobalApplicationComponent',
		),
Это не будет работать, т.к. в модуле test производится попытка preload компонента родительского модуля (приложения).
а при конфигурации внутри 'components' непосредственно модуля – такой способ не работает.
Это неправда. Следующий пример:

Код: Выделить всё

	// modules
	'modules'=>array(
		'test'=>array(
			'preload'=>array('testLocal'),
			'components'=>array(
				'testLocal'=>array(
					'class'=>'TestLocalApplicationComponent',
				),
			),
		),
	),
Все отлично работает. Теперь следующий пример:

Код: Выделить всё

	// modules
	'modules'=>array(
		'test'=>array(
			'preload'=>array('testShared'),
			'components'=>array(
				'testShared'=>array(
					'class'=>'TestSharedApplicationComponent',
					'prop'=>'Test module shared component',
				),
			),
		),
	),

	// application components
	'components'=>array(
		'testShared'=>array(
			'class'=>'TestSharedApplicationComponent',
			'prop'=>'Application shared component',
		),
Preload отлично работает. Оба компонента доступны следующими способами:

Код: Выделить всё

$this->module->testShared; // в контроллерах и видах main модуля (приложение) возвращает компонент testShared;
$this->module->testShared; // в контроллерах и видах test модуля (nested по отношению к main модулю) возвращает компонент testShared;
Yii::app()->testShared; // откуда угодно вернет компонент testShared main модуля (приложение);
Yii::app()->getModule('test')->testShared //откуда угодно вернет компонент testShared test модуля;
Думаю, что вооружившись полученными знаниями вы элегантно решите проблему с bootstrap.
Любой компонент привязанный к модулю будет глобальным getComponent опять же от app().
Это не так. Если взять в расчет конфигурацию плана:

Код: Выделить всё

	// modules
	'modules'=>array(
		'test'=>array(
			'preload'=>array('testLocal'),
			'components'=>array(
				'testLocal'=>array(
					'class'=>'TestLocalApplicationComponent',
				),
			),
		),
	),
то

Код: Выделить всё

Yii::app()->testLocal;
вызовет ошибку. Как и должно быть. Таким образом нет никаких несостыковок.

Таким образом резюмируем:
Я не могу конфигурировать компонент в модуле, потому что используется Yii::app()->bootstrap.
Можете.
Я не могу сделать preload компонентов не сконфигурированных для модуля
Не можете и замечательно, учитывая, что preload работает на уровне модуля, но только с теми компонентами, которые определены в конфигурации этого модуля.
Мне приходится использовать злое шаманство в виде Yii::app()->getComponent("bootstrap"); в init модуля.
Вариант не со злым шаманством я привел.
Возможно стоит при пооиске конфигурации компонента мержить его конфиг из модуля с глобальным?
Ни в коем случае. К чему такие неожиданные побочные эффекты? В 99% случаев это будет вредным эффектом, с которым ещё и придется бороться.
Возможно стоит сделать допустимым вызов компонентов текущего модуля через Yii::app()->%componentname%
Таким вызовом можно обратиться только к компонентам main модуля (приложение). Что касется возможности вызова компонентов текущего модуля, то делать её не нужно, т.к. они никуда не исчезала и существует практически с версии 1.0.0 фреймворка:

Код: Выделить всё

$this->module->[component_name]; // в контексте контроллера или вида и т.д.
Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Preload компонента в модуле

Сообщение lancecoder »

не знаю почему, но у меня не работают компоненты в модуле, если в ините вручную сеттер модулей не применить
Аватара пользователя
lancecoder
Сообщения: 2532
Зарегистрирован: 2012.06.26, 17:16

Re: Preload компонента в модуле

Сообщение lancecoder »

винда, опенсервер, апач
Аватара пользователя
creocoder
Сообщения: 138
Зарегистрирован: 2010.01.24, 05:29
Откуда: Тамбов

Re: Preload компонента в модуле

Сообщение creocoder »

Выложите конфиг приложения, будем смотреть...
Аватара пользователя
Loki
Сообщения: 65
Зарегистрирован: 2011.01.16, 10:47
Откуда: Омск

Re: Preload компонента в модуле

Сообщение Loki »

При конфиге:

Код: Выделить всё

'modules'        => array(
        'admin' => array(
            'preload' => array('bootstrap'),
            'components'     => array(
                'bootstrap'     => array(
                    'class'        => 'admin-ext.yii-bootstrap.components.Bootstrap'
                ),
            ),
        ),
    ),
),
Прелоад работает отлично, но падает тут

Код: Выделить всё

Не определено свойство "CWebApplication.bootstrap".
Я так понимаю, это баг YiiBootstrap, и им стоит отказаться от Yii::app()->bootstrap используя в виджетах $this->getController()->module?
Аватара пользователя
creocoder
Сообщения: 138
Зарегистрирован: 2010.01.24, 05:29
Откуда: Тамбов

Re: Preload компонента в модуле

Сообщение creocoder »

Я так понимаю, это баг YiiBootstrap
Исходя из ошибки, да. От жестких вызовов Yii::app()-> в гибких расширениях конечно стоит отказаться. Попробуйте связаться с автором расширения.
Аватара пользователя
Loki
Сообщения: 65
Зарегистрирован: 2011.01.16, 10:47
Откуда: Омск

Re: Preload компонента в модуле

Сообщение Loki »

Спасибо, из ваших ответов узнал действительно много полезного)
geralt
Сообщения: 1
Зарегистрирован: 2013.10.24, 17:46

Re: Preload компонента в модуле

Сообщение geralt »

Спасибо за информацию, сам столкнулся с этой проблемой. Исходя из вышеизложенного подключил компонент "Bootstrap" в модуле "admin" через конфиг "main", а вызовы типа

Код: Выделить всё

Yii::app()->bootstrap->*
в виджетах "Bootstrap" заменил на

Код: Выделить всё

Yii::app()->getModule('admin')->bootstrap->*
, Bootstrap нужен только в админке, обновлять его я не собираюсь. В Yii начинающий, подскажите, возможны косяки при такой реализации? Пока ошибок не было.
Ответить