You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 19:17:41