- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我做了一个自定义的Magento扩展,该扩展允许 bundle 的产品类型与“父” bundle 产品关联。
例如,如果我销售计算机零件,并且创建了一堆简单的产品类型(例如,键盘,鼠标,显示器等),并且我创建了 bundle 产品,该 bundle 产品将键盘和鼠标 bundle 在一起,可以与Magento一起使用必须提供开箱即用的功能。如果我创建了另一个 bundle 产品类型,但是这次我想 bundle 刚制作的 bundle 产品(带有键盘和鼠标的 bundle 产品),则无法执行此操作。因此,我要做的是创建一个扩展,使我可以将 bundle 的商品与 bundle 的商品相关联。
我在“本地”和“本地”下创建了一个新扩展名(我称之为Company
)。app/code/local/Company/etc/config.xml
<?xml version="1.0"?>
<config>
<global>
<blocks>
<bundle>
<rewrite>
<adminhtml_catalog_product_edit_tab_bundle_option_search_grid>Company_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Search_Grid</adminhtml_catalog_product_edit_tab_bundle_option_search_grid>
<adminhtml_catalog_product_composite_fieldset_options_type_checkbox>Company_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Checkbox</adminhtml_catalog_product_composite_fieldset_options_type_checkbox>
<catalog_product_view_type_bundle_option_checkbox>Company_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox</catalog_product_view_type_bundle_option_checkbox>
</rewrite>
</bundle>
</blocks>
<models>
<bundle>
<rewrite>
<product_type>Company_Bundle_Model_Product_Type</product_type>
</rewrite>
</bundle>
<bundle_resource>
<rewrite>
<option_collection>Company_Bundle_Model_Resource_Option_Collection</option_collection>
</rewrite>
</bundle_resource>
</models>
<catalog>
<product>
<type>
<bundle translate="label" module="bundle">
<label>Bundle Product</label>
<model>bundle/product_type</model>
<composite>1</composite>
<allowed_selection_types>
<simple/>
<bundle/>
<virtual/>
</allowed_selection_types>
<price_model>bundle/product_price</price_model>
<index_data_retreiver>bundle/catalogIndex_data_bundle</index_data_retreiver>
<index_priority>40</index_priority>
<price_indexer>bundle/indexer_price</price_indexer>
<stock_indexer>bundle/indexer_stock</stock_indexer>
</bundle>
</type>
<options>
<bundle>
<types>
<select translate="label" module="bundle">
<label>Drop-down</label>
</select>
<radio translate="label" module="bundle">
<label>Radio Buttons</label>
</radio>
<checkbox translate="label" module="bundle">
<label>Checkbox</label>
</checkbox>
<multi translate="label" module="bundle">
<label>Multiple Select</label>
</multi>
</types>
</bundle>
</options>
</product>
</catalog>
</global>
</config>
app/code/local/Company/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Bundle/Option/Search/Grid.php
<?php
class Company_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Search_Grid extends Mage_Bundle_Block_Adminhtml_Catalog_Product_Edit_Tab_Bundle_Option_Search_Grid
{
protected function _prepareCollection()
{
$collection = Mage::getModel('catalog/product')->getCollection()
->setStore($this->getStore())
->addAttributeToSelect('name')
->addAttributeToSelect('sku')
->addAttributeToSelect('price')
->addAttributeToSelect('attribute_set_id')
->addAttributeToFilter('type_id', array('in' => $this->getAllowedSelectionTypes()))
//->addFilterByRequiredOptions() OVERRIDE!
->addStoreFilter();
if ($products = $this->_getProducts()) {
$collection->addIdFilter($this->_getProducts(), true);
}
if ($this->getFirstShow()) {
$collection->addIdFilter('-1');
$this->setEmptyText($this->__('Please enter search conditions to view products.'));
}
Mage::getSingleton('catalog/product_status')->addSaleableFilterToCollection($collection);
$this->setCollection($collection);
return Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
}
protected function _prepareColumns()
{
$this->addColumn('id', array(
'header' => Mage::helper('sales')->__('ID'),
'sortable' => true,
'width' => '60px',
'index' => 'entity_id'
));
$this->addColumn('name', array(
'header' => Mage::helper('sales')->__('Product Name'),
'index' => 'name',
'column_css_class'=> 'name'
));
$sets = Mage::getResourceModel('eav/entity_attribute_set_collection')
->setEntityTypeFilter(Mage::getModel('catalog/product')->getResource()->getTypeId())
->load()
->toOptionHash();
$this->addColumn('set_name',
array(
'header'=> Mage::helper('catalog')->__('Attrib. Set Name'),
'width' => '100px',
'index' => 'attribute_set_id',
'type' => 'options',
'options' => $sets,
));
$this->addColumn('type',
array(
'header'=> Mage::helper('catalog')->__('Type'),
'width' => '60px',
'index' => 'type_id',
'type' => 'options',
'options' => Mage::getSingleton('catalog/product_type')->getOptionArray(),
));
$this->addColumn('sku', array(
'header' => Mage::helper('sales')->__('SKU'),
'width' => '80px',
'index' => 'sku',
'column_css_class'=> 'sku'
));
$this->addColumn('price', array(
'header' => Mage::helper('sales')->__('Price'),
'align' => 'center',
'type' => 'currency',
'currency_code' => $this->getStore()->getCurrentCurrencyCode(),
'rate' => $this->getStore()->getBaseCurrency()->getRate($this->getStore()->getCurrentCurrencyCode()),
'index' => 'price'
));
$this->addColumn('is_selected', array(
'header_css_class' => 'a-center',
'type' => 'checkbox',
'name' => 'in_selected',
'align' => 'center',
'values' => $this->_getSelectedProducts(),
'index' => 'entity_id',
));
$this->addColumn('qty', array(
'filter' => false,
'sortable' => false,
'header' => Mage::helper('sales')->__('Qty to Add'),
'name' => 'qty',
'inline_css'=> 'qty',
'align' => 'right',
'type' => 'input',
'validate_class' => 'validate-number',
'index' => 'qty',
'width' => '130px',
));
return Mage_Adminhtml_Block_Widget_Grid::_prepareColumns();
}
}
app/code/local/Company/Bundle/Block/Adminhtml/Catalog/Product/Composite/Fieldset/Options/Type/Checkbox.php
<?php
class Company_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Checkbox
extends Mage_Bundle_Block_Adminhtml_Catalog_Product_Composite_Fieldset_Options_Type_Checkbox
{
/**
* Set template
*
* @return void
*/
protected function _construct()
{
$this->setTemplate('Company/bundle/list.phtml');
}
/**
* @param string $elementId
* @param string $containerId
* @return string
*/
public function setValidationContainer($elementId, $containerId)
{
return '<script type="text/javascript">
$(\'' . $elementId . '\').advaiceContainer = \'' . $containerId . '\';
</script>';
}
}
app/code/local/Company/Bundle/Block/Catalog/Product/View/Type/Bundle/Option/Checkbox.php
<?php
class Company_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox
extends Mage_Bundle_Block_Catalog_Product_View_Type_Bundle_Option_Checkbox
{
/**
* Set template
*
* @return void
*/
protected function _construct()
{
$this->setTemplate('bundle/catalog/product/view/type/bundle/option/list.phtml');
}
}
app/code/local/Company/Bundle/Model/Product/Type.php
<?php
class Company_Bundle_Model_Product_Type extends Mage_Bundle_Model_Product_Type
{
/**
* Checking if we can sale this bundle
*
* @param Mage_Catalog_Model_Product $product
* @return bool
*/
public function isSalable($product = null)
{
$salable = Mage_Catalog_Model_Product_Type_Abstract::isSalable($product);
if (!is_null($salable)) {
return true; /* OVERRIDE! */
}
$optionCollection = $this->getOptionsCollection($product);
if (!count($optionCollection->getItems())) {
return false;
}
$requiredOptionIds = array();
foreach ($optionCollection->getItems() as $option) {
if ($option->getRequired()) {
$requiredOptionIds[$option->getId()] = 0;
}
}
$selectionCollection = $this->getSelectionsCollection($optionCollection->getAllIds(), $product);
if (!count($selectionCollection->getItems())) {
return false;
}
$salableSelectionCount = 0;
foreach ($selectionCollection as $selection) {
if ($selection->isSalable()) {
$requiredOptionIds[$selection->getOptionId()] = 1;
$salableSelectionCount++;
}
}
return (array_sum($requiredOptionIds) == count($requiredOptionIds) && $salableSelectionCount);
}
/**
* Retrive bundle selections collection based on used options
*
* @param array $optionIds
* @param Mage_Catalog_Model_Product $product
* @return Mage_Bundle_Model_Mysql4_Selection_Collection
*/
public function getSelectionsCollection($optionIds, $product = null)
{
$keyOptionIds = (is_array($optionIds) ? implode('_', $optionIds) : '');
$key = $this->_keySelectionsCollection . $keyOptionIds;
if (!$this->getProduct($product)->hasData($key)) {
$storeId = $this->getProduct($product)->getStoreId();
$selectionsCollection = Mage::getResourceModel('bundle/selection_collection')
->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
->addAttributeToSelect('tax_class_id') //used for calculation item taxes in Bundle with Dynamic Price
->setFlag('require_stock_items', true)
->setFlag('product_children', true)
->setPositionOrder()
->addStoreFilter($this->getStoreFilter($product))
->setStoreId($storeId);
//->addFilterByRequiredOptions() OVERRIDE!
//->setOptionIdsFilter($optionIds) OVERRIDE!
if (!Mage::helper('catalog')->isPriceGlobal() && $storeId) {
$websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
$selectionsCollection->joinPrices($websiteId);
}
$this->getProduct($product)->setData($key, $selectionsCollection);
}
return $this->getProduct($product)->getData($key);
}
/**
* Prepare product and its configuration to be added to some products list.
* Perform standard preparation process and then prepare of bundle selections options.
*
* @param Varien_Object $buyRequest
* @param Mage_Catalog_Model_Product $product
* @param string $processMode
* @return array|string
*/
protected function _prepareProduct(Varien_Object $buyRequest, $product, $processMode)
{
$result = Mage_Catalog_Model_Product_Type_Abstract::_prepareProduct($buyRequest, $product, $processMode);
if (is_string($result)) {
return $result;
}
$selections = array();
$product = $this->getProduct($product);
$isStrictProcessMode = $this->_isStrictProcessMode($processMode);
$skipSaleableCheck = Mage::helper('catalog/product')->getSkipSaleableCheck();
$_appendAllSelections = (bool)$product->getSkipCheckRequiredOption() || $skipSaleableCheck;
$options = $buyRequest->getBundleOption();
if (is_array($options)) {
$options = array_filter($options, 'intval');
$qtys = $buyRequest->getBundleOptionQty();
foreach ($options as $_optionId => $_selections) {
if (empty($_selections)) {
unset($options[$_optionId]);
}
}
$optionIds = array_keys($options);
if (empty($optionIds) && $isStrictProcessMode) {
return Mage::helper('bundle')->__('Please select options for product.');
}
$product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
$optionsCollection = $this->getOptionsCollection($product);
$selectionIds = array();
foreach ($options as $optionId => $selectionId) {
if (!is_array($selectionId)) {
if ($selectionId != '') {
$selectionIds[] = (int)$selectionId;
}
} else {
foreach ($selectionId as $id) {
if ($id != '') {
$selectionIds[] = (int)$id;
}
}
}
}
// If product has not been configured yet then $selections array should be empty
if (!empty($selectionIds)) {
$selections = $this->getSelectionsByIds($selectionIds, $product);
// Check if added selections are still on sale
foreach ($selections->getItems() as $key => $selection) {
if (!$selection->isSalable() && !$skipSaleableCheck) {
$_option = $optionsCollection->getItemById($selection->getOptionId());
if (is_array($options[$_option->getId()]) && count($options[$_option->getId()]) > 1) {
$moreSelections = true;
} else {
$moreSelections = false;
}
if ($_option->getRequired()
&& (!$_option->isMultiSelection() || ($_option->isMultiSelection() && !$moreSelections))
) {
return Mage::helper('bundle')->__('Selected required options are not available.');
}
}
}
$optionsCollection->appendSelections($selections, false, $_appendAllSelections);
$selections = $selections->getItems();
} else {
$selections = array();
}
} else {
$product->setOptionsValidationFail(true);
$product->getTypeInstance(true)->setStoreFilter($product->getStoreId(), $product);
$optionCollection = $product->getTypeInstance(true)->getOptionsCollection($product);
$optionIds = $product->getTypeInstance(true)->getOptionsIds($product);
$selectionIds = array();
$selectionCollection = $product->getTypeInstance(true)
->getSelectionsCollection(
$optionIds,
$product
);
$options = $optionCollection->appendSelections($selectionCollection, false, $_appendAllSelections);
foreach ($options as $option) {
if ($option->getRequired() && count($option->getSelections()) == 1) {
$selections = array_merge($selections, $option->getSelections());
} else {
$selections = array();
break;
}
}
}
if (count($selections) > 0 || !$isStrictProcessMode) {
$uniqueKey = array($product->getId());
$selectionIds = array();
// Shuffle selection array by option position
usort($selections, array($this, 'shakeSelections'));
foreach ($selections as $selection) {
if ($selection->getSelectionCanChangeQty() && isset($qtys[$selection->getOptionId()])) {
$qty = (float)$qtys[$selection->getOptionId()] > 0 ? $qtys[$selection->getOptionId()] : 1;
} else {
$qty = (float)$selection->getSelectionQty() ? $selection->getSelectionQty() : 1;
}
$qty = (float)$qty;
$product->addCustomOption('selection_qty_' . $selection->getSelectionId(), $qty, $selection);
$selection->addCustomOption('selection_id', $selection->getSelectionId());
$beforeQty = 0;
$customOption = $product->getCustomOption('product_qty_' . $selection->getId());
if ($customOption) {
$beforeQty = (float)$customOption->getValue();
}
$product->addCustomOption('product_qty_' . $selection->getId(), $qty + $beforeQty, $selection);
/*
* Create extra attributes that will be converted to product options in order item
* for selection (not for all bundle)
*/
$price = $product->getPriceModel()->getSelectionFinalTotalPrice($product, $selection, 0, $qty);
$attributes = array(
'price' => Mage::app()->getStore()->convertPrice($price),
'qty' => $qty,
'option_label' => $selection->getOption()->getTitle(),
'option_id' => $selection->getOption()->getId()
);
$_result = $selection->getTypeInstance(true)->prepareForCart($buyRequest, $selection);
if (is_string($_result) && !is_array($_result)) {
return $_result;
}
if (!isset($_result[0])) {
return Mage::helper('checkout')->__('Cannot add item to the shopping cart.');
}
$result[] = $_result[0]->setParentProductId($product->getId())
->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)))
->addCustomOption('bundle_selection_attributes', serialize($attributes));
if ($isStrictProcessMode) {
$_result[0]->setCartQty($qty);
}
$selectionIds[] = $_result[0]->getSelectionId();
$uniqueKey[] = $_result[0]->getSelectionId();
$uniqueKey[] = $qty;
}
// "unique" key for bundle selection and add it to selections and bundle for selections
$uniqueKey = implode('_', $uniqueKey);
foreach ($result as $item) {
$item->addCustomOption('bundle_identity', $uniqueKey);
}
$product->addCustomOption('bundle_option_ids', serialize(array_map('intval', $optionIds)));
$product->addCustomOption('bundle_selection_ids', serialize($selectionIds));
return $result;
}
return $this->getSpecifyOptionMessage();
}
/**
* Retrieve message for specify option(s)
*
* @return string
*/
public function getSpecifyOptionMessage()
{
return Mage::helper('bundle')->__('Please specify product option(s).');
}
}
app/code/local/Company/Bundle/Model/Resource/Option/Collection.php
<?php
class Company_Bundle_Model_Resource_Option_Collection extends Mage_Bundle_Model_Resource_Option_Collection
{
/**
* Append selection to options
* stripBefore - indicates to reload
* appendAll - indicates do we need to filter by saleable and required custom options
*
* @param Mage_Bundle_Model_Resource_Selection_Collection $selectionsCollection
* @param bool $stripBefore
* @param bool $appendAll
* @return array
*/
public function appendSelections($selectionsCollection, $stripBefore = false, $appendAll = true)
{
if ($stripBefore) {
$this->_stripSelections();
}
if (!$this->_selectionsAppended) {
foreach ($selectionsCollection->getItems() as $key => $_selection) {
if ($_option = $this->getItemById($_selection->getOptionId())) {
$_selection->setOption($_option);
$_option->addSelection($_selection);
}
}
$this->_selectionsAppended = true;
}
return $this->getItems();
}
}
protected function _prepareProduct(Varien_Object $buyRequest, $product, $processMode)
public function getSelectionsByIds($selectionIds, $product = null)
getItems()
提供了null。如果我删除
->addFilterByRequiredOptions()
getSelectionsByIds
,我可以从
getItems()
取回一些东西,但是它将崩溃
$_result = $selection->getTypeInstance(true)->prepareForCart($buyRequest, $selection);
最佳答案
开箱即用的建议,不需要如此复杂的解决方案。我们以magento的形式销售 bundle 套件,但我将它们设置为“简单产品”,而只是使用相关产品来分配任何类型的产品(在您的情况下,是其他 bundle 套件或任何其他类型的产品)。我们只需在产品页面上添加一个新块,即可根据需要显示相关产品,并为它提供套件内容的标题。当用户将商品添加到购物车时,它只是简单的产品。您也可以在购物车页面中添加一个块,以在购物车列表页面上该商品下方显示相关商品。从历史上看,我们在使用magento和 bundle 套件时遇到问题,有时人们无法在不删除并重新添加的情况下进行结帐,因此该解决方案可以完全解决问题,并为您提供所需的功能。虽然我们不使用管理员来管理产品或订单(所有操作都通过api和后台完成),但是可以将原则应用于管理员等中。
关于Magento: bundle 未添加到购物车,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16200699/
Magento 主题和 Magento 皮肤有什么区别?它们和 Magento 模块之间有什么关系? 最佳答案 主题是创建视觉体验的布局、模板、区域设置和/或外观文件的任意组合... 主题由以下任意或
我想在 Magento 之外获得购物车 Block。这是我的代码。 getLocale()->getLocaleCode(); //Solution Mage::getSingleto
我是 Magento 新手,使用 CE 1.7.0.2 开发了一个网站。现在可以上线了,但我遇到了页面加载缓慢的问题。 我的网站产品主页、列表和详细信息页面最初需要 10-13 秒的时间来加载页面,但
我在 magento 网站上工作。我有 4 个类别,其中两个使用其他主题(不是我的特定 magento 主题)。我如何配置我的主题以从我的默认主题而不是基本主题中获取丢失的文件。 谢谢 最佳答案 通常
我遇到了我的 magento 项目的要求,因此我需要为特定客户群的购买提供特别折扣。此折扣必须显示在客户帐户中,如果他们属于该特定组,并且当用户要使用该特定折扣时,必须根据该折扣优惠对该商品的价格进行
我在 Magento 主题开发中找到的大量教程建议从使用空白作为制作您自己的自定义主题的指南开始。很多这些文章已经很旧了,截至当前版本(1.7),情况仍然如此吗? 附言- 除了 Magento 的 o
似乎这应该是一个可以找到的问题,但我找不到它。 magento 数据库中存储的类别 NAME 在哪里?我可以看到 catalog_category_entity有 key ID,然后还有其他 EAV
我知道 magento 会根据需要调整原始产品图像的大小并以不同的大小对其进行多次缓存。 这些 chached 图像存储在哪里(路径)? 当您从缓存管理中刷新图像缓存时,它们会被删除吗? 如果我要手动
我在我的 magento 网上商店中使用这个扩展 http://www.manadev.com/seo-layered-navigation-plus (分层导航) 此扩展适用于简单的产品。 但就我而
我在 Magento 的一家商店下拥有某些产品的批发属性。我想设置它,以便这些特定属性仅出现在产品页面上,如果客户已登录并且他们在批发客户组中。 这可能吗? 最佳答案 像这样的事情应该可以工作,尽管我
和有什么区别和 在 Magento 中? 我将创建一个新模块,我必须决定在这两个事件中的哪一个事件中挂起我的观察者。 最佳答案 类别(和所有其他对象)保存在事务中。事件catalog_categor
好吧,这是一个似乎很容易解决的问题,但它让我望而却步...... 我的 Magento Web 上有一些类别,每个类别都有一些产品。我希望它们显示为 4 列计数,但它始终显示为 3 列计数,如下所示:
我已经在我的网站上添加了一些成员(member)跟踪代码。为了使跟踪工作正常进行,我需要向关联公司提供确认付款的网址。 我正在使用Magento,我不确定该版本,但几年内未对其进行更新。我需要知道订单
我们的网站遇到了问题。 系统 > 配置屏幕仅显示菜单、侧面菜单和页脚。当我们点击侧边菜单选项时,屏幕仍然黑屏,相关信息也没有出现。请看 this link .这就是出现的情况。当我们点击任何侧面菜单选
我想只使用一个 csv 文件来翻译前端 Magento 商店。所以我这样做了: 我创建了一个名为 Translator 的自定义模块。在其 config.xml 中,我放置了以下几行: ....
我添加了自定义订单状态选项。 有谁知道我如何通过API将其设置为自定义值? 最佳答案 感谢Diglin为我指出的正确位置。只是为了正确地给出答案: 您可以使用addComment方法来执行此操作,该方
目前,Magento 处理大规模操作的方式存在问题。无论分页如何,它都会返回一些 JS,其中包含当前集合和过滤器的每个 db id。这是为了支持网格标题中的“全选”与“全选可见”选项。当您的记录数量较
如何收集具有此角色的所有角色(系统->权限->角色)和用户? 谢谢。 最佳答案 获得所有角色 $roles = Mage::getModel('admin/roles')->getCol
如果能在我网站的各种应用程序之间进行通用登录,那将是一种巨大的用户体验。现在,我有一个 Magento 店面和一个 IPS 板社区。我正在尝试将它们集成到我的用户的一个通用登录中。 IPS 板提供多种
我正在为 Magento 社区 1.4.2 版中的时尚客户开发一个网站,作为该项目的一部分,我需要一些定制的主页促销块来展示特定产品或产品类别。为此,我想我会编写自己的小部件,并且除了如何处理图像外,
我是一名优秀的程序员,十分优秀!