我在为Magento商店创建自定义模块时遇到了问题。
我已经成功添加了一个路径(/ landing),并创建了/在我的基本布局中显示模板内容的布局文件。我现在需要超越这一点。
我希望能够从URL加载参数,根据该参数获取对象,并根据对象的内容显示内容。
示例:用户浏览器到domain.com/landing/cool/。这(希望)会调用着陆控制器。控制器会以某种方式拉出'酷'参数,然后拉出与酷相关联的着陆对象。然后,我的模板可以获取该对象并显示其元素。
我知道那里有很多东西,但是我已经开了一段时间并且无处可去。 Magento必须为其所有类别,项目等执行此操作。有没有人知道我该怎么做?
答案 0 :(得分:2)
如果您执行domain.com/landing/[controller]/cool/[key]/[value],您可以执行$ this-> getRequest() - > getParam('[key]')来获取[value]的值。然后,您可以根据该模板设置模板,但我认为这是一个不同的问题。如果您仍然感到困惑,请告诉我。
答案 1 :(得分:2)
以下解释假设您已按照常规方式定义了您的前缀:
<config>
<modules>
<Mycompany_Landing>
<version>0.1.0</version>
</Mycompany_Landing>
</modules>
<frontend>
<routers>
<landing>
<use>standard</use>
<args>
<module>Mycompany_Landing</module>
<frontName>landing</frontName>
</args>
</landing>
</routers>
</frontend>
</config>
在这种情况下,Magento标准路由器会将URL landing/cool
映射到
Mycompany_Landing_CoolController::indexAction()
这是因为Magento标准路由器使用frontname/controller/action
模式处理URL,在您的情况下,它知道
landing
,映射到Mycompany_Landing
模块cool
,将转换为CoolController
indexAction
但您希望cool
成为参数,而不是控制器。
我猜这背后的原因是你希望除了landing/cool
之外还有多个着陆区,例如landing/awesome
,landing/insane
等等。这意味着您必须设置多个控制器,每个控制器对应一个不同的着陆区。
在这种情况下,避免多个控制器的可能解决方案是实现自己的路由器。
要实现自己的路由器,您需要挂钩controller_front_init_routers
事件,例如通过像这样扩展你的app/code/local/Mycompany/Landing/etc/config.xml
:
<config>
<global>
<events>
<controller_front_init_routers>
<observers>
<landing>
<class>Mycompany_Landing_Controller_Router</class>
<method>controllerFrontInitRouters</method>
</landing>
</observers>
</controller_front_init_routers>
</events>
</global>
</config>
接下来创建一个合适的app/code/local/Mycompany/Landing/Controller/Router.php
文件:
class Mycompany_Landing_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{
/**
* Add own router to Magento router chain
*
* @param Varien_Event_Observer $oObserver
*/
public function controllerFrontInitRouters($oObserver)
{
// Add this router to the current router chain
$oObserver
->getEvent()
->getFront()
->addRouter('landing', $this);
}
/**
* Match routes for the landing module
*
* @param Zend_Controller_Request_Http $oRequest
* @return bool
*/
public function match(Zend_Controller_Request_Http $oRequest)
{
$sPathInfo = trim($oRequest->getPathInfo(), '/');
$aPathInfo = explode('/', $sPathInfo);
// Cancel if the route request is for some other module
if ($aPathInfo[0] != 'landing') {
return false;
}
// Cancel if it's not a valid landing zone
if (!in_array($aPathInfo[1], array('cool'))) {
return false;
}
// Rewrite the request object
$oRequest
->setModuleName('landing')
->setControllerName('index')
->setActionName('index')
->setParam('zone', $aPathInfo[1])
->setAlias(
'landing_router_rewrite',
true
);
// Tell Magento that this router can match the request
return true;
}
}
上述文件的controllerFrontInitRouters()
方法会将您自己的路由器合并到Magento路由器链中,以便它看起来像这样:
Mage_Core_Controller_Varien_Router_Admin
Mage_Core_Controller_Varien_Router_Standard
Mage_Cms_Controller_Router
Mycompany_Landing_Controller_Router
Mage_Core_Controller_Varien_Router_Default
Magento将在调度时按给定顺序循环此链。这意味着,像您这样的自定义路由器最早会在第4个位置被调用。如果前三个路由器中没有一个路由器已经匹配路由请求,则只会调用您的路由器。
当调用文件的match()
方法并检测到有效路由时(仅当前为landing/cool
),它将更改请求对象,以便Mycompany_Landing_IndexController::indexAction()
将被分派,参数zone
,其值为cool
。
请注意,此match()
过于简单。它不包含消毒等。不要忘记解决这个问题^^
最后创建一个app/code/local/Mycompany/Landing/controllers/IndexController.php
文件:
class Mycompany_Landing_IndexController extends Mage_Core_Controller_Front_Action
{
public function indexAction()
{
if (!$this->getRequest()->getAlias('landing_router_rewrite')) {
$this->_forward('noRoute');
return;
}
$sZone = $this->getRequest()->getParam('zone');
die(__METHOD__ . ' called with zone = ' . $sZone);
}
}
如果请求对象中没有设置if
别名,则indexAction
的第一个landing_route_rewrite
块会取消操作(请参阅路由器setAlias()
中的match()
方法)。
这样做是因为用户也可以使用indexAction()
,landing
,landing/index
,landig/index/index
等其他网址来覆盖此landing/index/index/zone/cool
。上。
我想您不希望其他网址被SEO排名,也不希望两次实施验证和清理,但如果您不需要,只需删除if
阻止。
现在,您可以扩展indexAction()
以执行您对着陆区所做的任何操作。
答案 2 :(得分:1)
我稍后会在这里稍微调查一下,但是现在我想到的唯一一件就是'/'来抓住它们。
答案 3 :(得分:0)
以下是我通过Javascript为我的一个项目做的事情:
function populateSelect(url, element, target) {
var selectedValue = document.getElementById(element);
var elementValue = selectedValue.options[selectedValue.selectedIndex].value;
pathArray = url.split( '/' );
pathArray.shift();
pathArray.shift();
pathArray.splice(5,0, element);
pathArray.splice(6,0, elementValue);
url = pathArray.join("/");
url = 'http://' + url;
new Ajax.Request(url, {
method: "POST",
onSuccess:
function(transport) {
var json = transport.responseText.evalJSON(true);
var options = '';
$(target).descendants().each(Element.remove);
for (var i = 0; i < json.length; i++) {
var opt = document.createElement('option');
opt.text = json[i].optionName;
opt.value = json[i].optionValue;
$(target).options.add(opt);
}
}
});
}