我正在为Magento社区版本1.4.2中的时尚客户开发一个网站,作为该项目的一部分,我需要有一些自定义主页推广块来展示特定产品或产品类别。为此,我想我会编写自己的小部件,除了如何处理图像外,在这方面取得了很大的进步。我需要将图片作为促销的一部分。在我的小部件定义文件中,我包含以下参数
<image>
<label>Image</label>
<description>Promotion image</description>
<visible>1</visible>
<type>image</type>
</image>
这似乎起初工作正常,当在管理员后端创建/编辑窗口小部件时,窗口小部件选项中包含文件上载字段,但是在保存表单时,图像似乎没有上载,或者其详细信息保留在数据库中。有没有其他人有在小部件中使用图像的经验以及我可能做错了什么?
答案 0 :(得分:25)
有几个原因导致它无法保存/上传图像:
enctype
需要为“multipart/form-data
”才能上传文件enctype
更改为“multipart/form-data
”,您也会注意到,如果您监控它被POST为“application/x-www-form-urlencoded
”的请求,这是因为它已完成通过ajax和ajax本身无法处理文件上传,您需要单独处理它们。我已成功实施“插入图片”按钮,该按钮初始化Media Library
对话框,您可以在其中浏览服务器以查找图像和/或上传图像。
用户点击“插入文件”后,会将完整的图片网址插入到窗口小部件的文本框中,以便将其像普通字段一样传递到模板中。
这就是我实现它的方式:
在您的widget.xml中指定一个新节点:
<image translate="label">
<label>Image</label>
<visible>1</visible>
<required>1</required>
<type>label</type>
<helper_block>
<type>widgets/cms_wysiwyg_images_chooser</type>
<data>
<button translate="open">
<open>Insert Image...</open>
</button>
</data>
</helper_block>
</image>
帮助程序块类型<type>widgets/cms_wysiwyg_images_chooser</type>
是一个自定义类,因此只要正确创建类/文件,就可以将其更改为任何所需的类型。
<?php
class Stackoverflow_Widgets_Block_Cms_Wysiwyg_Images_Chooser extends Mage_Adminhtml_Block_Template
{
public function prepareElementHtml(Varien_Data_Form_Element_Abstract $element)
{
$config = $this->getConfig();
$chooseButton = $this->getLayout()->createBlock('adminhtml/widget_button')
->setType('button')
->setClass('scalable btn-chooser')
->setLabel($config['button']['open'])
->setOnclick('MediabrowserUtility.openDialog(\''.$this->getUrl('*/cms_wysiwyg_images/index', array('target_element_id' => $element->getName())).'\')')
->setDisabled($element->getReadonly());
$text = new Varien_Data_Form_Element_Text();
$text->setForm($element->getForm())
->setId($element->getName())
->setName($element->getName())
->setClass('widget-option input-text');
if ($element->getRequired()) {
$text->addClass('required-entry');
}
if ($element->getValue()) {
$text->setValue($element->getValue());
}
$element->setData('after_element_html', $text->getElementHtml().$chooseButton->toHtml());
return $element;
}
}
?>
就是这样!您现在应该在窗口小部件选项中有一个名为“Image”的新字段,其中包含一个文本框和一个按钮,您可以在其中将URL插入服务器上的图像并从模板中显示它。
快速解释其工作原理:
创建一个具有onclick
功能的按钮,通过调用Media Library
来调用MediabrowserUtility.openDialog()
对话,并传递参数target_element_id
,该参数告诉媒体库在用户点击“Insert File
”后设置该值,以便我们只是传递小部件中文本框的id
,以便接收用户选择的图像的网址。
希望这有助于某人,因为我找不到任何解释如何做的资源所以我花了很长时间挖掘Magento来全力以赴:)
我将来要做的是让它在小部件中选择后显示图像,并将url存储在隐藏字段中,但不会触发onchange
绑定当值设置为js/mage/adminhtml/browser.js
函数中insert
的元素时,因此不更改核心文件就更难了。在Media Library
关闭或计时器(相当笨拙但可以工作)之后,我想到了表单再次聚焦的时候,但是我还有其他事情可以继续下去,可能会在以后再回来!
<强>更新强>
Media Library
生成的网址如下:
http://www.yourwebsite.com/index.php/admin/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvd2lkZ2V0cy9iYW5uZXIvaG9tZXBhZ2UvZm9yZWdyb3VuZC9maXNoLXRhbmsucG5nIn19/key/e8167e3884e40b97d8985e7b84e7cbc7875f134e5f7e5946c9c2a482d0279762/
哪些是缓存图片,仅在用户是管理员时才有效。笨?是。如果在为输出生成html时将同一图像插入CMS页面,则会将其转换为可通过/media/wysiwyg/path/to/file/photo.jpg
访问的服务器上的原始URL。我们需要向用户显示原始URL,因此我们可以做的是挂钩生成小部件html的函数(当您单击“插入小部件”时)并查找/admin/cms_wysiwyg/directive/___directive/
并将其替换为原始URL CMS页面的图像。
在您的自定义小部件的config.xml
中:
<global>
<models>
<widget>
<rewrite>
<widget>Stackoverflow_Widgets_Model_Widget</widget>
</rewrite>
</widget>
</models>
</global>
然后创建模型窗口小部件code\local\Stackoverflow\Widgets\Model\Widget.php
:
<?php
class Stackoverflow_Widgets_Model_Widget extends Mage_Widget_Model_Widget
{
public function getWidgetDeclaration($type, $params = array(), $asIs = true)
{
foreach($params as $k => $v){
if(strpos($v,'/admin/cms_wysiwyg/directive/___directive/') !== false){
$parts = explode('/',parse_url($v, PHP_URL_PATH));
$key = array_search('___directive', $parts);
if($key !== false){
$directive = $parts[$key+1];
$src = Mage::getModel('core/email_template_filter')->filter(Mage::helper('core')->urlDecode($directive));
if(!empty($src)){
$params[$k] = parse_url($src, PHP_URL_PATH);
}
}
}
}
return parent::getWidgetDeclaration($type, $params, $asIs);
}
}
覆盖每次为textarea / wysiwyg生成窗口小部件输出时调用的getWidgetDeclaration
函数,并查看所有参数,如果找到链接到管理缓存的图像,它将查找取出原始图像并覆盖数组中的变量,并使用参数调用原始函数。
如果找不到缓存的图像,该功能将正常工作。
更新日期:13/09/2012
正如Jonathan Day指出的那样,如果你想让它在Widget实例中工作,你也必须覆盖Mage_Widget_Model_Widget_Instance
。
到目前为止,我还没有必要通过Widget实例向窗口小部件添加图像,并且为什么我的函数不起作用而感到困惑,直到我调查并意识到“弹出窗口”窗口小部件实例使用{{1}在Widget选项选项卡(没有弹出窗口)上使用的窗口小部件实例是Mage_Widget_Model_Widget
,并且不扩展Mage_Widget_Model_Widget_Instance
所以不要继承该功能。
要将功能添加到Mage_Widget_Model_Widget
,只需将行Mage_Widget_Model_Widget_Instance
添加到<widget_instance>Petbarn_Widgets_Model_Widget_Instance</widget_instance>
,这样就会显示如下:
config.xml
然后创建模型Instance <global>
<models>
<widget>
<rewrite>
<widget>Stackoverflow_Widgets_Model_Widget</widget>
<widget_instance>Stackoverflow_Widgets_Model_Widget_Instance</widget_instance>
</rewrite>
</widget>
</models>
</global>
:
code\local\Stackoverflow\Widgets\Model\Widget\Instance.php
这次我们正在修改<?php
class Petbarn_Widgets_Model_Widget_Instance extends Mage_Widget_Model_Widget_Instance
{
protected function _beforeSave()
{
if (is_array($this->getData('widget_parameters'))) {
$params = $this->getData('widget_parameters');
foreach($params as $k => $v){
if(strpos($v,'/cms_wysiwyg/directive/___directive/') !== false){
$parts = explode('/',parse_url($v, PHP_URL_PATH));
$key = array_search('___directive', $parts);
if($key !== false){
$directive = $parts[$key+1];
$src = Mage::getModel('core/email_template_filter')->filter(Mage::helper('core')->urlDecode($directive));
if(!empty($src)){
$params[$k] = parse_url($src, PHP_URL_PATH);
}
}
}
}
$this->setData('widget_parameters', $params);
}
return parent::_beforeSave();
}
}
函数开头的widget_parameters
数据,以便在保存之前修复网址。
您还必须确保包含_beforeSave()
javascript文件(在我的情况下不是),以获得/js/mage/adminhtml/browser.js
功能。
为了确保包含它,最简单的方法是将其包含在所有管理员中(没有花太多时间更好地定位它)。
为adminhtml布局创建MediabrowserUtility
(如果您还没有):local.xml
app\design\adminhtml\default\default\layout\local.xml
这将使Magento在管理员的每个页面上都包含<?xml version="1.0"?>
<layout version="0.1.0">
<default>
<reference name="head">
<action method="addJs"><script>mage/adminhtml/browser.js</script></action>
</reference>
</default>
</layout>
,因此js/mage/adminhtml/browser.js
始终可用。
注意:我正在使用Magento Enterprise 1.11.2.0,所以我不确定它在其他版本上的表现。
答案 1 :(得分:9)
我通过为小部件创建自定义字段类型来解决此用例:
<image>
<label>Image</label>
<description>Promotion image</description>
<visible>1</visible>
<type>widgetimagechooser/chooser</type>
</image>
我实现了一个触发标准Magento图像选择器元素的块Aijko_WidgetImageChooser_Block_Chooser
。
为了解决图像文件的非清除URL的问题,我实现了一个自定义控制器Aijko_WidgetImageChooser_Adminhtml_Cms_Wysiwyg_Images_ChooserController
,它处理来自Magento标准图像选择器的返回值。
该值将添加到窗口小部件的文本框中。然后,该图像的相对URL可用于在前端显示图像。
您可以尝试Github上提供的扩展程序,也可以使用Magento Connect直接安装。
答案 2 :(得分:2)
谢谢你的回答!我找到了一种更好的方法来解决缓存图像URL的问题。我甚至不得不这样做,因为覆盖Widget模型的解决方案不适用于Magento 1.7.0.2。
所以我所做的是在用于Chooser Block的URL中添加一个新的GET参数use_file_url
:
$url = $this->getUrl(
'*/cms_wysiwyg_images/index',
array(
'target_element_id' => $element->getName(),
'use_file_url' => 1
)
);
这会将GET参数传递给媒体浏览器。下一步是将此参数传递给onInsertAction
的{{1}}。这样做,您必须覆盖Mage_Adminhtml_Cms_Wysiwyg_ImagesController
阻止的getOnInsertUrl()
功能:
Mage_Adminhtml_Block_Cms_Wysiwyg_Images_Content
然后你需要处理public function getOnInsertUrl()
{
$useFileUrl = (int)$this->getRequest()->getParam('use_file_url', 0);
return $this->getUrl('*/*/onInsert', array('use_file_url' => $useFileUrl));
}
控制器中的新参数:
Mage_Adminhtml_Cms_Wysiwyg_ImagesController
最后一步是覆盖public function onInsertAction()
{
$useFileUrl = (int)$this->getRequest()->getParam('use_file_url', 0) == 1 ? true : false;
$helper = Mage::helper('cms/wysiwyg_images');
$storeId = $this->getRequest()->getParam('store');
$filename = $this->getRequest()->getParam('filename');
$filename = $helper->idDecode($filename);
$asIs = $this->getRequest()->getParam('as_is');
Mage::helper('catalog')->setStoreId($storeId);
$helper->setStoreId($storeId);
if ($useFileUrl == false) {
$image = $helper->getImageHtmlDeclaration($filename, $asIs);
} else {
$image = $helper->getImageMediaUrl($filename);
}
$this->getResponse()->setBody($image);
}
助手并添加Mage_Cms_Helper_Wysiwyg_Images
功能:
getImageMediaUrl()
我认为这是一个非常漂亮的方法,即使你必须完成4个类。但是,传递GET参数似乎比解析缓存的URL更安全。
答案 3 :(得分:1)
Magento的图片自定义属性通常不会出现在扩展标签中,您必须转到目录&gt;产品&gt;要分配此属性的图像。但是通过一些自定义编码,您可以实现这一目标。
答案 4 :(得分:0)
小部件没有文件上传。要解决这个问题你可以使用magento媒体浏览器并选择图像为wysiwyg编辑器,但还有其他问题,媒体浏览器不会返回清晰的图像URL。
答案 5 :(得分:0)
从Magento 1.9.2.0开始,您还需要将以下内容添加到您的adminhtml布局文件中:
lib/flex.js
lib/FABridge.js
mage/adminhtml/flexuploader.js