我无法创建我的Magento商店的自定义模块。
我已经成功添加的路由(/登陆),以及显示我的基地布局内的模板内容创建/配置文件。 我现在需要能够超越这一点。
我希望能够从URL中加载一个参数,抢基于该参数的对象,显示基于我的对象的内容的东西。
例如:用户的浏览器domain.com/landing/cool/。 这(希望)将调用登陆控制器。 控制器会在一定程度能够拉动“酷”的参数,并拉凉爽相关联的着陆对象。 然后,我的模板可以得到该对象并显示其内容。
我知道有很多位,但我一直在破解这个我的头一会儿还是一无所获。 Magento的有它的所有类别,项目做到这一点,等没有人有知道我该怎么办呢?
如果你这样做domain.com/landing/[controller]/cool/[key]/[value],你可以做到这 - $> Request()方法 - > getParam(“[关键]”)来获得[价值的价值]。 然后,您可以设置基于该模板,但我认为这是一个不同的问题。 让我知道如果你还在困惑。
下面的解释假定您已经定义了frontname通常的方式:
<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的标准路由器将网址映射landing/cool
到
Mycompany_Landing_CoolController::indexAction()
这是因为Magento的标准路由器使用处理URL frontname/controller/action
模式,在你的情况下,它知道
- 所述frontname是
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
,等等。
我猜你不希望有这样的其他URL被搜索引擎优化排名,也没有实施验证和消毒两次,但如果你不需要它,只是删除if
块。
现在,您可以延长indexAction()
做任何你想用你的着陆区做。
我正把它多一点在这里了一会儿,但现在这是未来想到的唯一的事情是在爆炸“/”抓住他们。
下面是我做到了通过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);
}
}
});
}