Magento 2技术问题:phtml获取自定义URL与文章ID路由页面开发
嘿,我来帮你搞定这两个Magento 2的开发问题,都是实际项目里常碰到的场景,一步步给你捋清楚:
问题1:在Magento 2的phtml文件中获取自定义URL
获取自定义URL有两种常用方式,优先推荐符合Magento规范的依赖注入方式:
方法1:依赖注入(推荐,利于维护和扩展)
先在对应页面的Block类中注入\Magento\Framework\UrlInterface,封装一个获取URL的方法:<?php namespace Vendor\Module\Block; use Magento\Framework\View\Element\Template; use Magento\Framework\UrlInterface; class CustomBlock extends Template { protected $urlBuilder; public function __construct( Template\Context $context, UrlInterface $urlBuilder, array $data = [] ) { $this->urlBuilder = $urlBuilder; parent::__construct($context, $data); } // 自定义方法获取URL public function getCustomPageUrl() { // 示例1:获取自定义路由的URL(frontname/controller/action) return $this->urlBuilder->getUrl('customroute/index/view', ['id' => 123]); // 示例2:获取自定义CMS页面的URL(用页面标识符) // return $this->urlBuilder->getUrl(null, ['_direct' => 'custom-cms-page']); } }然后在phtml模板中调用Block的方法:
<a href="<?= $block->getCustomPageUrl() ?>">点击跳转到自定义页面</a>方法2:直接在phtml中调用(应急用,不推荐长期使用)
如果只是临时快速实现,也可以直接在phtml里用Template类封装好的getUrl()方法:<!-- 获取自定义路由URL --> <a href="<?= $this->getUrl('customroute/index/view', ['id' => 456]) ?>">跳转</a> <!-- 获取CMS页面URL --> <a href="<?= $this->getUrl(null, ['_direct' => 'about-us']) ?>">关于我们</a>注:这种方式跳过了依赖注入原则,不利于代码维护,尽量只在临时场景使用。
问题2:实现posts表的/id形式URL并获取文章数据
要实现your-magento-url/5这种直接用ID访问文章的效果,需要完成一套自定义模块开发,步骤如下:
步骤1:创建基础模块(以Vendor_Post为例)
先创建模块的核心注册文件:
app/code/Vendor/Post/registration.php
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Vendor_Post', __DIR__ );
app/code/Vendor/Post/etc/module.xml
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Post" setup_version="1.0.0"> <sequence> <module name="Magento_Framework"/> </sequence> </module> </config>
步骤2:配置自定义路由匹配器(实现/id格式URL)
我们需要让Magento识别数字ID形式的URL,创建自定义路由匹配器:
- 首先在
app/code/Vendor/Post/etc/di.xml注册路由:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Framework\App\RouterList"> <arguments> <argument name="routerList" xsi:type="array"> <item name="post_router" xsi:type="array"> <item name="class" xsi:type="string">Vendor\Post\Controller\Router</item> <item name="disable" xsi:type="boolean">false</item> <item name="sortOrder" xsi:type="string">20</item> </item> </argument> </arguments> </type> </config>
- 然后创建路由匹配类
app/code/Vendor/Post/Controller/Router.php:
<?php namespace Vendor\Post\Controller; use Magento\Framework\App\ActionFactory; use Magento\Framework\App\RequestInterface; use Magento\Framework\App\ResponseInterface; use Magento\Framework\Url; use Vendor\Post\Model\PostFactory; class Router implements \Magento\Framework\App\RouterInterface { protected $actionFactory; protected $response; protected $postFactory; public function __construct( ActionFactory $actionFactory, ResponseInterface $response, PostFactory $postFactory ) { $this->actionFactory = $actionFactory; $this->response = $response; $this->postFactory = $postFactory; } public function match(RequestInterface $request) { $identifier = trim($request->getPathInfo(), '/'); // 检查URL是否为纯数字ID if (is_numeric($identifier)) { $postId = (int)$identifier; $post = $this->postFactory->create()->load($postId); // 如果文章存在,转发到控制器处理 if ($post->getId()) { $request->setModuleName('post') ->setControllerName('view') ->setActionName('index') ->setParam('id', $postId); $request->setAlias(Url::REWRITE_REQUEST_PATH_ALIAS, $identifier); return $this->actionFactory->create(\Magento\Framework\App\Action\Forward::class); } } return null; // 不匹配则交给其他路由处理 } }
步骤3:创建模型/资源模型操作posts表
创建操作数据库的模型类,用于读取posts表数据:
- 模型:
app/code/Vendor/Post/Model/Post.php
<?php namespace Vendor\Post\Model; use Magento\Framework\Model\AbstractModel; class Post extends AbstractModel { protected function _construct() { $this->_init(\Vendor\Post\Model\ResourceModel\Post::class); } }
- 资源模型:
app/code/Vendor/Post/Model/ResourceModel/Post.php
<?php namespace Vendor\Post\Model\ResourceModel; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; class Post extends AbstractDb { protected function _construct() { $this->_init('posts', 'post_id'); // 对应数据库表名和主键字段 } }
步骤4:创建控制器处理请求
创建控制器加载文章数据并传递给模板:app/code/Vendor/Post/Controller/View/Index.php
<?php namespace Vendor\Post\Controller\View; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; use Magento\Framework\View\Result\PageFactory; use Vendor\Post\Model\PostFactory; class Index extends Action { protected $resultPageFactory; protected $postFactory; public function __construct( Context $context, PageFactory $resultPageFactory, PostFactory $postFactory ) { $this->resultPageFactory = $resultPageFactory; $this->postFactory = $postFactory; parent::__construct($context); } public function execute() { $postId = $this->getRequest()->getParam('id'); $post = $this->postFactory->create()->load($postId); // 文章不存在则跳转到404 if (!$post->getId()) { $this->_forward('noroute'); return; } // 加载页面并传递文章数据 $resultPage = $this->resultPageFactory->create(); $block = $resultPage->getLayout()->getBlock('post.view'); if ($block) { $block->setPost($post); } // 设置页面标题为文章标题 $resultPage->getConfig()->getTitle()->set($post->getTitle()); return $resultPage; } }
步骤5:创建模板展示文章数据
- 布局文件:
app/code/Vendor/Post/view/frontend/layout/post_view_index.xml
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="content"> <block class="Vendor\Post\Block\View" name="post.view" template="Vendor_Post::view.phtml"/> </referenceContainer> </body> </page>
- Block类:
app/code/Vendor/Post/Block/View.php
<?php namespace Vendor\Post\Block; use Magento\Framework\View\Element\Template; use Vendor\Post\Model\Post; class View extends Template { protected $post; public function setPost(Post $post) { $this->post = $post; return $this; } public function getPost() { return $this->post; } }
- phtml模板:
app/code/Vendor/Post/view/frontend/templates/view.phtml
<?php /** @var \Vendor\Post\Block\View $block */ ?> <?php $post = $block->getPost(); ?> <div class="single-post"> <h1 class="post-title"><?= $block->escapeHtml($post->getTitle()) ?></h1> <div class="post-content"> <?= $block->escapeHtml($post->getText()) ?> </div> <!-- 其他字段可按需获取,比如创建时间:<?= $block->escapeHtml($post->getCreatedAt()) ?> --> </div>
步骤6:启用模块并刷新缓存
运行以下命令完成模块部署:
bin/magento module:enable Vendor_Post bin/magento setup:upgrade bin/magento cache:flush
现在访问your-magento-url/5,就能展示posts表中ID为5的文章标题和内容了。
内容的提问来源于stack exchange,提问作者Ihor Mandzyuk
相关产品推荐
相关产品推荐

