- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我们商店的起始页上有一个小部件。
店铺使用FPC和block cache。
如果管理员在后台更改小部件设置,我们如何更新小部件内容?
是否可以在CacheKey中使用Widget的配置数据?
或者我们是否必须将缓存生命周期设置得非常小?
编辑:我自己的答案使用缓存生命周期。只有当小部件实例被编辑时,才从 FPC 中有针对性地清除缓存 block 的方法是什么?
最佳答案
第一步是创建前端小部件本身,但要提供一些可供完整页面缓存使用的额外信息。
第二步是在整个页面缓存中为小部件处理打洞。
第三步是如果在管理区域中更改了该小部件,则仅自动清除该小部件的小部件缓存。
首先,为您的模块创建 etc/widget.xml 文件:
<widgets>
<netzarbeiter_test type="netzarbeiter_test/widget_test">
<name>FPC Holepunch Cache Test</name>
<description>Dummy test widget</description>
<parameters>
<!-- This is the important parameter here: -->
<unique_id>
<required>1</required>
</unique_id>
<example_text>
<visible>1</visible>
<label>Example Text Parameter</label>
<type>text</type>
</example_text>
</parameters>
</netzarbeiter_test>
</widgets>
注意参数 <unique_id>
.我们不提供输入类型或值,Mage_Widget_Block_Adminhtml_Widget_Options::_addField()
会自动用生成的值填充它方法:
// Excerpt from Mage_Widget_Block_Adminhtml_Widget_Options::_addField()
if ($values = $this->getWidgetValues()) {
$data['value'] = (isset($values[$fieldName]) ? $values[$fieldName] : '');
}
else {
$data['value'] = $parameter->getValue();
//prepare unique id value
if ($fieldName == 'unique_id' && $data['value'] == '') {
$data['value'] = md5(microtime(1));
}
}
因为有了这个小 gem ,我们不必重写 Mage_Widget_Model_Widget_Instance
类以将小部件 ID 注入(inject)到生成的布局 xml 中。
接下来,创建小部件类本身。这只是一个实现 Mage_Widget_Block_Interface
的常规 block 实例接口(interface),除了unique_id
用于 cacheKeyInfo
方法。
class Netzarbeiter_Test_Block_Widget_Test
extends Mage_Core_Block_Abstract
implements Mage_Widget_Block_Interface
{
public function getCacheKeyInfo()
{
$info = parent::getCacheKeyInfo();
if ($id = $this->getData('unique_id')) {
// Because the array key is a string, it will be added to the FPC placeholder
// parameters. That is how the FPC container can access it (see below).
$info['unique_id'] = (string) $id;
}
return $info;
}
protected function _toHtml()
{
// The FPC was completely cleared (or not created yet),
// recreate the widget parameter cache
if (! $this->getFullPageCacheEnvironment() && $this->getUniqueId()) {
$id = Netzarbeiter_Test_Model_Fpc_Container_Widget_Test::CACHE_PREFIX . $this->getUniqueId() . '_params';
Enterprise_PageCache_Model_Cache::getCacheInstance()->save(serialize($this->getData()), $id);
}
// Just some dummy output to display the text parameter and the render time
$time = now();
$textParam = $this->escapeHtml($this->getExampleText());
return <<<EOF
<p><b>Render Time:</b> {$time}<br/>
<b>Example Text:</b> {$textParam}<br/></p>
EOF;
}
}
当我们现在通过管理界面添加一个小部件实例时,unique_id
widget.xml 中指定的参数将被添加到布局 xml(为便于阅读而添加的格式:
SELECT layout_update_id, handle, xml FROM core_layout_update;
+------------------+--------------------------+----------------------------------------------------------------------------------------------------+
| layout_update_id | handle | xml |
+------------------+--------------------------+----------------------------------------------------------------------------------------------------+
| 17 | catalog_category_layered | <reference name="left">
| | | <block type="netzarbeiter_test/widget_test" name="2a3b55e13549e176709fc6c67a4a7bd8">
| | | <action method="setData">
| | | <name>unique_id</name>
| | | <value>7fa2574145ef204fb6d179cfc604ac76</value>
| | | </action>
| | | <action method="setData">
| | | <name>example_text</name>
| | | <value>This is a String!</value>
| | | </action>
| | | </block>
| | | </reference>
+------------------+--------------------------+----------------------------------------------------------------------------------------------------+
这意味着,每当通过布局 xml 渲染创建 block 实例时,unique_id
参数将在 block 对象上已知。
添加 etc/cache.xml 文件:
<config>
<placeholders>
<cms_block_widget>
<block>netzarbeiter_test/widget_test</block>
<placeholder>WIDGET_FPC_TEST</placeholder>
<container>Netzarbeiter_Test_Model_Fpc_Container_Widget_Test</container>
</cms_block_widget>
</placeholders>
</config>
接下来,创建容器类:
class Netzarbeiter_Test_Model_Fpc_Container_Widget_Test
extends Enterprise_PageCache_Model_Container_Abstract
{
const CACHE_PREFIX = 'TEST_WIDGET_';
protected function _getCacheId()
{
return self::CACHE_PREFIX . $this->_placeholder->getAttribute('unique_id');
}
protected function _renderBlock()
{
$block = $this->_getPlaceHolderBlock();
// Set any parameters from the placeholder on the block as needed.
// See observer below where the current parameters are cached.
$id = $this->_getCacheId() . '_params';
if ($parameters = Enterprise_PageCache_Model_Cache::getCacheInstance()->load($id)) {
$block->addData(unserialize($parameters));
// Set environment information on block (used in _toHtml,
// the params cache is recreated when not set)
$block->setFullPageCacheEnvironment(true);
}
Mage::dispatchEvent('render_block', array('block' => $block, 'placeholder' => $this->_placeholder));
return $block->toHtml();
}
}
这就是使我们的小部件成为完全缓存页面中的动态 block 所需的全部。但到目前为止,小部件 block 被无限期缓存。我们仍然需要处理缓存刷新。
为自动 *_save_commit_after
使用事件观察器所有 Magento 模型都提供特定于小部件实例的事件。每次在管理界面中保存小部件实例时都会触发它。
<adminhtml>
<events>
<widget_widget_instance_save_commit_after>
<observers>
<netzarbeiter_test>
<model>netzarbeiter_test/observer</model>
<method>widgetWidgetInstanceSaveCommitAfter</method>
</netzarbeiter_test>
</observers>
</widget_widget_instance_save_commit_after>
</events>
</adminhtml>
最后一 block 拼图是观察者方法:
public function widgetWidgetInstanceSaveCommitAfter(Varien_Event_Observer $observer)
{
/** @var $widget Mage_Widget_Model_Widget_Instance */
$widget = $observer->getEvent()->getObject();
$parameters = $widget->getWidgetParameters();
$uniqueId = isset($parameters['unique_id']) ? $parameters['unique_id'] : '';
if (strlen($uniqueId)) {
$id = Netzarbeiter_Test_Model_Fpc_Container_Widget_Test::CACHE_PREFIX . $uniqueId;
Enterprise_PageCache_Model_Cache::getCacheInstance()->remove($id);
$id = Netzarbeiter_Test_Model_Fpc_Container_Widget_Test::CACHE_PREFIX . $uniqueId . '_params';
Enterprise_PageCache_Model_Cache::getCacheInstance()->save(serialize($parameters), $id);
}
}
现在前端的实例会在每次保存时自动更新,即使有激活的全页缓存。在所有其他时间,将从缓存中获取动态 block 。
编辑:将缓存的小部件参数示例添加到代码中,因为正如 Alex 在下面的评论中指出的那样,只要 FPC 条目存在,占位符参数就不会刷新。
使用缓存将widget参数传递给block,避免了在block动态渲染时重写widget实例模型和加载widget实例。
关于php - Magento:如果小部件参数发生变化,则从 block /整页缓存中刷新小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11436380/
我在 JavaScript 文件中运行 PHP,例如...... var = '';). 我需要使用 JavaScript 来扫描字符串中的 PHP 定界符(打开和关闭 PHP 的 )。 我已经知道使
我希望能够做这样的事情: php --determine-oldest-supported-php-version test.php 并得到这个输出: 7.2 也就是说,php 二进制检查 test.
我正在开发一个目前不使用任何框架的大型 php 站点。我的大问题是,随着时间的推移慢慢尝试将框架融入应用程序是否可取,例如在创建的新部件和更新的旧部件中? 比如所有的页面都是直接通过url服务的,有几
下面是我的源代码,我想在同一页面顶部的另一个 php 脚本中使用位于底部 php 脚本的变量 $r1。我需要一个简单的解决方案来解决这个问题。我想在代码中存在的更新查询中使用该变量。 $name)
我正在制作一个网站,根据不同的情况进行大量 PHP 重定向。就像这样...... header("Location: somesite.com/redirectedpage.php"); 为了安全起见
我有一个旧网站,我的 php 标签从 因为短标签已经显示出安全问题,并且在未来的版本中将不被支持。 关于php - 如何避免在 php 文件中写入
我有一个用 PHP 编写的配置文件,如下所示, 所以我想用PHP开发一个接口(interface),它可以编辑文件值,如$WEBPATH , $ACCOUNTPATH和 const值(value)观
我试图制作一个登录页面来学习基本的PHP,首先我希望我的独立PHP文件存储HTML文件的输入(带有表单),但是当我按下按钮时(触发POST到PHP脚本) )我一直收到令人不愉快的错误。 我已经搜索了S
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: What is the max key size for an array in PHP? 正如标题所说,我想知道
我正在寻找一种让 PHP 以一种形式打印任意数组的方法,我可以将该数组作为赋值包含在我的(测试)代码中。 print_r 产生例如: Array ( [0] => qsr-part:1285 [1]
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 9 年前。 Improve this ques
我在 MySQL 数据库中有一个表,其中存储餐厅在每个工作日和时段提供的菜单。 表结构如下: i_type i_name i_cost i_day i_start i_
我有两页。 test1.php 和 test2.php。 我想做的就是在 test1.php 上点击提交,并将 test2.php 显示在 div 中。这实际上工作正常,但我需要向 test2.php
我得到了这个代码。我想通过textarea更新mysql。我在textarea中回显我的MySQL,但我不知道如何更新它,我应该把所有东西都放进去吗,因为_GET模式没有给我任何东西,我也尝试_GET
首先,我是 php 的新手,所以我仍在努力学习。我在 Wordpress 上创建了一个表单,我想将值插入一个表(data_test 表,我已经管理了),然后从 data_test 表中获取所有列(id
我有以下函数可以清理用户或网址的输入: function SanitizeString($var) { $var=stripslashes($var); $va
我有一个 html 页面,它使用 php 文件查询数据库,然后让用户登录,否则拒绝访问。我遇到的问题是它只是重定向到 php 文件的 url,并且从不对发生的事情提供反馈。这是我第一次使用 html、
我有一个页面充满了指向 pdf 的链接,我想跟踪哪些链接被单击。我以为我可以做如下的事情,但遇到了问题: query($sql); if($result){
我正在使用 从外部文本文件加载 HTML/PHP 代码 $f = fopen($filename, "r"); while ($line = fgets($f, 4096)) { print $l
我是一名优秀的程序员,十分优秀!