我正在 Magento 社区版本 1.4.2 中为时尚客户开发一个网站,作为该项目的一部分,我需要一些定制的主页促销块来展示特定的产品或产品类别。为此,我想我应该编写自己的小部件,并且除了如何处理图像之外,在这方面已经取得了相当好的进展。我需要添加图片作为促销的一部分。在我的小部件定义文件中,我包含了以下参数
<image>
<label>Image</label>
<description>Promotion image</description>
<visible>1</visible>
<type>image</type>
</image>
,这起初似乎工作正常,在管理后端创建/编辑小部件时,小部件选项中包含文件上传字段,但是在保存表单时,图像似乎没有显示上传,或其详细信息保留在数据库中。还有其他人有在小部件中使用图像的经验吗?我可能做错了什么?
I am developing a site for a fashion client in Magento Community version 1.4.2 and as part of this project I need to have some customized home page promotion blocks to feature specific products or categories of products. For this I thought I would write my own widget and have made pretty good progress in this with the exception of how to deal with images. I need to include an image as part of the promotion. In my widget definition file I included the following parameter
<image>
<label>Image</label>
<description>Promotion image</description>
<visible>1</visible>
<type>image</type>
</image>
This seemed at first to work fine and when creating/editing a widget in the admin back end a file upload field is included in the widget options however on saving the form the image does not appear to be uploaded, or its details retained in the database. Does anyone else have experience of using images in widgets and what I may be doing wrong?
发布评论
评论(6)
它不保存/上传图像有几个原因:
enctype
需要为“multipart/form-data
”才能上传文件enctype
更改为“multipart/form-data
”,您会注意到,如果您监视请求,它会被 POST 为“application/x” -www-form-urlencoded
"这是因为它是通过ajax完成的,ajax本身无法处理文件上传,需要单独处理。我已经成功实现了“插入图像”按钮,该按钮初始化
媒体库
对话框,您可以在其中浏览服务器中的图像和/或上传图像。用户单击“插入文件”后,它会将完整图像 URL 插入小部件中的文本框中,以便它像普通字段一样传递到模板中。
这就是我实现它的方法:
在您的 widget.xml 中指定一个新节点:
辅助块类型
widgets/cms_wysiwyg_images_chooser
是一个自定义类,因此您可以将其更改为只要正确创建类/文件,您想要的任何东西都可以。就是这样!现在,您的小部件选项中应该有一个名为“图像”的新字段,其中包含一个文本框和一个按钮,您可以在其中插入服务器上图像的 url 并从模板中显示它。
对其工作原理的快速说明:
创建一个具有
onclick
函数的按钮,该函数通过调用MediabrowserUtility.openDialog()
来调用Media Library
对话框> 其中传递了参数target_element_id
,该参数告诉媒体库在用户单击“Insert File
”后要在哪个元素中设置值,因此我们只需传递id
小部件中的文本框,用于接收用户选择的图像的 url。希望这对某人有帮助,因为我找不到任何资源来解释如何做到这一点,所以我花了很长时间挖掘 Magento 来解决所有问题:)
我将来想做的就是拥有它,这样它就可以了。在小部件中选择图像后显示图像,并将 url 存储在隐藏字段中,但是当值设置为
js/ 中的元素时,不会触发
在onchange
绑定mage/adminhtml/browser.jsinsert
函数中,因此在不更改核心文件的情况下很难做到这一点。我考虑过在媒体库
关闭或计时器关闭后表单再次获得焦点时进行尝试(相当狡猾,但会起作用),但我还有其他事情要做,可能会回到它之后!更新:
媒体库
生成的URL如下所示:http://www.yourwebsite.com/index.php/admin/cms_wysiwyg/directive/ ___指令/e3ttZWRpYSB1cmw9Ind5c2l3eWcvd2lkZ2V0cy9iYW5uZXIvaG9tZXBhZ2UvZm9yZWdyb3VuZC9maXNoLXRhbmsucG5nIn19/key/e8167e3884e40b97d8985e7b84e7cbc7 875f134e5f7e5946c9c2a482d0279762/
这是缓存的图像,仅当用户是管理员时才有效。愚蠢的?是的。如果您在生成输出 html 时将相同的图像插入 CMS 页面,它会将其转换为服务器上可通过
/media/wysiwyg/path/to/file/photo.jpg
。我们需要向用户显示原始网址,因此我们可以做的是挂钩生成小部件 html 的函数(当您单击“插入小部件”时)并查找/admin/cms_wysiwyg/directive/___directive/
并将其替换为图像的原始 URL,就像 CMS 页面一样。在您的自定义小部件的
config.xml
中:然后创建模型小部件
code\local\Stackoverflow\Widgets\Model\Widget.php
:它会覆盖
getWidgetDeclaration
函数,每次为 textarea/wysiwyg 生成小部件输出时都会调用该函数,并查看所有参数,如果找到链接到管理缓存的图像,它将找出原始图像并覆盖数组中的变量并使用参数调用原始函数。如果未找到缓存的图像,该功能将正常工作。
更新:13/09/2012
正如 Jonathan Day 指出的,如果您希望它在 Widget 实例中工作,您也必须覆盖
Mage_Widget_Model_Widget_Instance
。直到现在,我还不需要通过小部件实例将图像添加到小部件,并且很困惑为什么我的功能不起作用,直到我调查并意识到“弹出”小部件实例使用
Mage_Widget_Model_Widget
并且在“窗口小部件选项”选项卡(无弹出窗口)上使用的窗口小部件实例是Mage_Widget_Model_Widget_Instance
,并且不会扩展Mage_Widget_Model_Widget
,因此不会继承该功能。要将功能添加到
Mage_Widget_Model_Widget_Instance
,只需将行Petbarn_Widgets_Model_Widget_Instance
添加到您的config.xml
中即可,如下所示:然后创建模型实例
code\local\Stackoverflow\Widgets\Model\Widget\Instance.php
:这次我们修改
widget_parameters
开头的数据code>_beforeSave() 函数,以便在保存之前修复 url。您还必须确保包含
/js/mage/adminhtml/browser.js
javascript 文件(在我的例子中没有包含)才能获取MediabrowserUtility
功能。为了确保它被包含在内,最简单的方法是将它包含在所有管理员中(没有花太多时间更好地瞄准它)。
为 adminhtml 布局创建一个
local.xml
(如果您还没有):app\design\adminhtml\default\default\layout\local.xml
这将使 Magento 在管理的每个页面上包含 js/mage/adminhtml/browser.js ,以便 MediabrowserUtility 始终可用。
注意:我使用的是 Magento Enterprise 1.11.2.0,所以我不确定它在其他版本上的表现如何。
There are a couple reason why it doesn't save/upload the image:
enctype
needs to be "multipart/form-data
" for a file upload to workenctype
to "multipart/form-data
" you will notice if you monitor the requests that it gets POST'ed as "application/x-www-form-urlencoded
" this is because it is done through ajax and ajax by itself can't process a file upload, you need to process them separately.I have successfully implemented a "Insert Image" button which initialises the
Media Library
dialogue where you can browse your server for images and/or upload images.Once the user clicks "Insert File" it inserts the full image url into a textbox in the widget so it's passed along like a normal field to your template.
This is how I achieved it:
In your widget.xml specify a new node:
The helper block type
<type>widgets/cms_wysiwyg_images_chooser</type>
is a custom class, so you can change it to anything you want as long as you create the class/files correctly.And that is it! You should now have a new field in your widget options called "Image" with a textbox and a button in which you can insert the url to an image on your server and display it from your template.
A quick explanation of how it works:
A button is created that has an
onclick
function that calls theMedia Library
dialogue by callingMediabrowserUtility.openDialog()
which along is passed the parametertarget_element_id
which tells media library what element to set the value in once they user clicks "Insert File
" so we simply pass along theid
of our textbox in the widget for it to receive the url of the image that the user selected.Hope this helps someone as I couldn't find any resources out there that explained how to do it so I spent quite a while digging through Magento to work it all out :)
What I would like to do in the future is have it so it displays the image after you select it in the widget, and it stores the url in a hidden field, but having an
onchange
bind is not fired when the value is set to the element fromjs/mage/adminhtml/browser.js
in theinsert
function, so without changing the core files it is a lot harder to do. I thought about playing around with when the form gets focus again after theMedia Library
closes or a timer (pretty dodgey but would work), but I have other things to move on to and may come back to it later!UPDATE:
The URL's that the
Media Library
generates are like so:http://www.yourwebsite.com/index.php/admin/cms_wysiwyg/directive/___directive/e3ttZWRpYSB1cmw9Ind5c2l3eWcvd2lkZ2V0cy9iYW5uZXIvaG9tZXBhZ2UvZm9yZWdyb3VuZC9maXNoLXRhbmsucG5nIn19/key/e8167e3884e40b97d8985e7b84e7cbc7875f134e5f7e5946c9c2a482d0279762/
Which are a cached image, and only work if the user is an admin. Stupid? Yes. If you insert the same image in to a CMS page when the html is generated for output it converts it to the original url on the server accessible via
/media/wysiwyg/path/to/file/photo.jpg
. We need the original url to show to the user, so what we can do is hook into the function that generates the widget html (when you click "Insert Widget") and look for/admin/cms_wysiwyg/directive/___directive/
and replace it with the original URL to the image as the CMS page does.In your
config.xml
for your custom widgets:Then create the model Widget
code\local\Stackoverflow\Widgets\Model\Widget.php
:Which overrides the
getWidgetDeclaration
function which is called every time a the widget output is produced for a textarea/wysiwyg and looks through all the parameters and if it finds an image that is linked to the admin cache it will find out the original image and overwrite the variable in the array and call the original function with the parameters.If the cached image is not found the function will work as normal.
UPDATE: 13/09/2012
As Jonathan Day pointed out you have to overwrite
Mage_Widget_Model_Widget_Instance
also if you want it to work in a Widget Instance.I haven't had the need to add an image to a widget through a Widget Instance until now and was confused why my function didn't work, until I investigated and realised the "popup" widget instances use
Mage_Widget_Model_Widget
and the widget instances that are used on a Widget options tab (no popup) areMage_Widget_Model_Widget_Instance
and do not extendMage_Widget_Model_Widget
so do not inherit the functionality.To add the functionality to
Mage_Widget_Model_Widget_Instance
simply add the line<widget_instance>Petbarn_Widgets_Model_Widget_Instance</widget_instance>
to yourconfig.xml
so it will look like:Then create the model Instance
code\local\Stackoverflow\Widgets\Model\Widget\Instance.php
:This time we are modifying the
widget_parameters
data at the start of the_beforeSave()
function so it fixes up the url before it saves it.You also have to ensure the
/js/mage/adminhtml/browser.js
javascript file is included (in my case it wasn't) to get theMediabrowserUtility
functionality.To ensure it is included, the easiest way is to include it for all of admin (didn't spend much time targeting it better).
Create a
local.xml
for adminhtml layouts (if you don't already have one):app\design\adminhtml\default\default\layout\local.xml
This will make Magento include
js/mage/adminhtml/browser.js
on every page of admin soMediabrowserUtility
will always be available.NOTE: I'm using Magento Enterprise 1.11.2.0 so I'm not sure how it behaves on other versions.
我通过为小部件创建自定义字段类型解决了这个用例:
我实现了一个块
Aijko_WidgetImageChooser_Block_Chooser
来触发标准 Magento 图像选择器元素。为了解决图像文件 URL 不清晰的问题,我实现了一个自定义控制器
Aijko_WidgetImageChooser_Adminhtml_Cms_Wysiwyg_Images_ChooserController
来处理 Magento 标准图像选择器的返回值。该值将添加到小部件中的文本框中。然后可以使用该图像的相对 url 在前端显示图像。
请随意尝试 Github 上提供的扩展或直接使用 Magento 连接。
I solved this use case by creating a custom field type for widgets:
I implemented a block
Aijko_WidgetImageChooser_Block_Chooser
that triggers the standard Magento image chooser element.To solve the problem with the non clear url to the image file I implemented a custom controller
Aijko_WidgetImageChooser_Adminhtml_Cms_Wysiwyg_Images_ChooserController
that handles the return value from the Magento standard image chooser.The value is added to a textbox in the widget. This relative url to the image then can be used to show the image in the frontend.
Feel free to try the extension available on Github or install directly using Magento Connect.
谢谢克鲁斯的回答!我找到了一种更好的方法来解决缓存图像 URL 的问题。我什至不得不这样做,因为您覆盖 Widget 模型的解决方案不适用于 Magento 1.7.0.2。
因此,我所做的就是将新的 GET 参数
use_file_url
添加到用于选择器块的 URL:这会将 GET 参数传递到媒体浏览器。下一步是将此参数传递给
Mage_Adminhtml_Cms_Wysiwyg_ImagesController
的onInsertAction
。为此,您必须重写Mage_Adminhtml_Block_Cms_Wysiwyg_Images_Content
块的getOnInsertUrl()
函数:然后您需要在
Mage_Adminhtml_Cms_Wysiwyg_ImagesController
中处理新参数控制器:最后一步是覆盖
Mage_Cms_Helper_Wysiwyg_Images
帮助器并添加getImageMediaUrl()
函数:我认为这是一个非常漂亮的方法,即使您必须 ovverride 4 个类。但传递 GET 参数似乎比解析缓存的 URL 更安全。
Thx krus for you answer! I've found a nicer way to solve the problem with the cached image URLs. I even had to do this, because your solution overwriting the Widget Model didn't work with Magento 1.7.0.2.
So what I have done is adding a new GET parameter
use_file_url
to the URL used for the Chooser Block:This passes the GET parameter to the media browser. The next step is to pass this parameter to the
onInsertAction
of theMage_Adminhtml_Cms_Wysiwyg_ImagesController
. Do do this, you have to override thegetOnInsertUrl()
function of theMage_Adminhtml_Block_Cms_Wysiwyg_Images_Content
Block:Then you need to handle the new parameter in the
Mage_Adminhtml_Cms_Wysiwyg_ImagesController
controller:The last step is to override the
Mage_Cms_Helper_Wysiwyg_Images
helper and add thegetImageMediaUrl()
function:I think this is a quite pretty approach, even though you have to ovverride 4 classes. But passing a GET parameter seems to be more future safe than parsing the cached URL.
小部件没有文件上传。要解决这个问题,您可以使用 magento 媒体浏览器并像所见即所得编辑器一样选择图像,但还有其他问题,媒体浏览器不返回图像的清晰 url。
There is no file uploads for widgets. To solve that problem you may use magento media browser and select image like for wysiwyg editor, but there is other issue, media browser do not return clear url of image.
从 Magento 版本 1.9.2.0 开始,您还需要将以下内容添加到 adminhtml 布局文件中:
As of Magento version 1.9.2.0 you will also need to add the following to your adminhtml layout file:
Magento 的图像自定义属性通常不会出现在扩展选项卡中,您必须转到“目录”>“产品”>“扩展”选项卡。用于分配此属性的图像。但通过一些自定义编码,您可以实现这一目标。
Magento's Image custom attributes normally does not come to extension tab and you will have to go to Catalog>Product> Images to assign this attribute. But with some custom coding you can achieve this.