Como verificar se existe um bloco (com base em seu tipo)
-
11-12-2019 - |
Pergunta
Isso realmente me confunde!!
Cheguei a uma situação em que preciso criar um novo bloco (core/template
bloco) programaticamente, se houver Bloco CMS presente em um layout de página.Em geral, de acordo com meu conhecimento, existem duas soluções alternativas para isso.
1.Adicione um bloco através do layout
Na maioria dos casos, esta seria a melhor ideia para realizar esta tarefa.Podemos adicionar um bloco a uma página se um identificador de layout apropriado estiver disponível.Mas, infelizmente, no meu caso, não tenho nenhum identificador de layout específico de bloco estático disponível (para páginas cms, sabemos que existe cms_page
lidar).Então não posso confiar neste método
2.Use um observador
O segundo método seria ouvir um observador apropriado.Novamente, não consigo encontrar um observador baseado em bloco estático que seja acionado durante o tempo de carregamento do layout/bloco.No entanto, existem alguns observadores gerais em quem posso confiar.Eu penso controller_action_layout_generate_blocks_before
pode usar no meu caso.Mas aqui estou eu enfrentando meu verdadeiro problema
Meu verdadeiro problema
Então quando eu uso controller_action_layout_generate_blocks_before
evento no meu caso, o problema é que não consigo recuperar blocos com base em seu tipo.Posso filtrar blocos com base em seus name
, mas não com base em seus type
.ou seja
$observer->getEvent()->getLayout()->getBlock('block_name'); //this work; Used name
$observer->getEvent()->getLayout()->getBlock('cms/block'); //this wont; use type
Na verdade, não posso confiar em nomes. Porque eu quero pegar tudo cms/block
digite blocos e adicione um novo modelo depois de verificar algumas de suas propriedades personalizadas que defini com bloco estático
Então, como posso obter tudo cms/block
através de um observador?É mesmo possível.Por favor, compartilhe seus pensamentos.
Solução
Usa isto:
<core_block_abstract_prepare_layout_before>
<observers>
<ssd_test>
<class>ssd_test/observer</class>
<method>generateBlocks</method>
<type>singleton</type>
</ssd_test>
</observers>
</core_block_abstract_prepare_layout_before>
Observador:
public function generateBlocks($observer)
{
/**
* @var $block Mage_Core_Block_Abstract
*/
$block = $observer->getEvent()->getBlock();
if ($block->getType() == 'cms/block') {
//do something
}
}
Referir-se protected function _toHtml()
do Mage_Cms_Block_Block
se você quiser fazer algumas alterações.
Atualização (outra solução)
<controller_action_layout_generate_blocks_after>
<observers>
<ssd_test>
<class>ssd_test/observer</class>
<method>generateBlocks</method>
<type>singleton</type>
</ssd_test>
</observers>
</controller_action_layout_generate_blocks_after>
Observador.php:
public function generateBlocks($observer)
{
/**
* @var $l Mage_Core_Model_Layout
*/
$l = $observer->getEvent()->getLayout();
$newBlock = $l->createBlock(
'Mage_Core_Block_Template',
'new_block_name_here',
array('template' => 'some_template.phtml')
);
foreach ($l->getAllBlocks() as $block) {
if ($block->getType() == 'cms/block') {
$l->getBlock('some_block_name')->append($newBlock);
}
}
}
Outras dicas
Você não poderia simplesmente ouvir o evento core_block_abstract_to_html_before
então verifique o tipo de bloco no evento e atualize o modelo com base nisso?Algo como o seguinte deve bastar.
$block = $observer->getBlock();
if ($block instanceof Mage_Cms_Block_Block) {
// Make your changes here
}
Isso funcionaria para todos os blocos, mas se você sabe que isso só acontece em alguns casos, sugiro alterar o modelo via layout xml.
Ou se você quiser acrescentar algo a um bloco, mas deixar o original como está, você pode usar o core_block_abstract_to_html_after
pegue o transport
passou para o evento.Em seguida, coloque o html em relação a isso e anexe o que você precisa.Novamente, este evento fornece o bloco para que você possa limitar seu código de maneira simples Mage_Cms_Block_Block
$block = $observer->getBlock();
if ($block instanceof Mage_Cms_Block_Block) {
$transport = $observer->getTransport();
$html = $transport->getHtml();
$html .= 'We need to append something here';
$transport->setHtml($html);
}
Pelo que me lembro, você pode obter todos os blocos como uma coleção ou como uma matriz do layout e, em seguida, verificar seu tipo usando o operador "instância de".