netzmacht/contao-page-context

这个库提供了一些工具,用于为自定义路由启动Contao页面上下文。

资助包维护!
dmolineus

安装次数: 16,128

依赖项: 2

建议者: 0

安全: 0

星星: 3

关注者: 2

分支: 1

开放性问题: 0

类型:contao-bundle

1.2.1 2024-02-07 15:38 UTC

This package is auto-updated.

Last update: 2024-09-07 16:59:18 UTC


README

Build Status Version License Downloads Contao Community Alliance coding standard

这个Contao扩展允许开发者在使用自定义路由时手动启动Contao的页面上下文。

Contao CMS的一些部分依赖于在渲染页面时初始化的全局状态。模块、内容元素、插入标记和自定义扩展可能会依赖于这种状态已初始化。

例如,Contao开发者通过访问$GLOBALS['objPage']来获取当前页面,因为没有其他方法可以获取当前页面。

然而,当使用自定义入口点,例如API时,您没有初始化这种状态。使用Contao库和功能可能会导致意外的错误。

这正是这个扩展介入的地方。它允许您为您的路由手动启动页面上下文。

具体来说,它初始化以下步骤:

  • Contao框架
  • 如果未定义,将常量BE_USER_LOGGED_INFE_USER_LOGGED_IN设置为false
  • 从数据库中加载页面
  • 全局变量objPageTL_ADMIN_NAMETL_ADMIN_EMAILTL_KEYWORDSTL_LANGUAGE
  • 初始化请求的本地化和翻译器
  • 加载默认语言文件
  • 调用Controller::initializeStaticUrls()
  • 初始化页面布局(触发getPageLayout钩子)

要求

  • Contao ^4.9
  • PHP ^7.1 || ^8.0

安装

php composer.phar require netzmacht/contao-page-context --update-no-dev -o 

使用

1. 实现一个PageIdDeterminator并正确注册它

首先,您必须提供一个PageIdDeterminator。它负责从给定的请求中提取页面ID。

您应该将确定器限制到您的特殊用例,这就是为什么存在match()方法。

<?php

declare(strict_types=1);

namespace My\Bundle;

use Netzmacht\Contao\PageContext\Request\PageIdDeterminator;
use Netzmacht\Contao\PageContext\Exception\DeterminePageIdFailed;
use Symfony\Component\HttpFoundation\Request;

final class MyPageIdDeterminator implements PageIdDeterminator
{
    public function match(Request $request): bool
    {
        return ($request->attributes->get('_my_context') === 'page');
    }

    public function determinate(Request $request): int
    {
        if (!$request->attributes->has('pageId')) {
            throw new DeterminePageIdFailed('Could not determine page id for from request.');
        }

        return $request->attributes->getInt('pageId');
    }
}

现在,您必须将其注册为服务,并标记为Netzmacht\Contao\PageContext\Request\PageIdDeterminator

<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="https://symfony.ac.cn/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="https://symfony.ac.cn/schema/dic/services
        https://symfony.ac.cn/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="My\Bundle\MyPageIdDeterminator">
            <tag name="Netzmacht\Contao\PageContext\Request\PageIdDeterminator" />
        </service>
    </services>
</container>

2. 准备您的路由

如上面示例所示,已访问自定义路由属性,这里是_my_context。您应该在路由配置中定义它

<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="https://symfony.ac.cn/schema/routing"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://symfony.ac.cn/schema/routing
        https://symfony.ac.cn/schema/routing/routing-1.0.xsd">

    <route id="my_route" controller="My\Bundle\Action\ApiAction" path="/my/api/{pageId}" >
        <default key="_my_context">page</default>
        <default key="_scope">frontend</default>
        <requirement key="pageId">\d+</requirement>
    </route>
</routes>

3. 访问页面对象

这就完成了。如果您尝试访问$GLOBALS['objPage'],您应该有页面对象。好消息是,您可以避免访问全局状态。您的当前请求有一个新属性,称为_page_context

<?php

declare(strict_types=1);

namespace My\Bundle\Action;

use Netzmacht\Contao\PageContext\Request\PageContext;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

final class ApiAction
{
    public function __invoke(Request $request): Response
    {
        /** @var PageContext $context */
        $context = $request->attributes->get('_page_context');

        return new JsonResponse(
            [
                'pageId' => $context->page()->id,
                'rootId' => $context->rootPage()->id,
            ]
        );
    }
}