contenir/cache-laminas-mvc 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

contenir/cache-laminas-mvc

Composer 安装命令:

composer require contenir/cache-laminas-mvc

包简介

Laminas MVC adapter for contenir/cache — MvcEvent page-cache listener driven by the standard pagecache config.

README 文档

README

Laminas MVC adapter for contenir/cache.

A page-cache MvcEvent listener with the legacy cache_with_* / make_id_with_* shape preserved, driven by the standard pagecache config key. Admin-side toggles (pagecache.options.cache, per-route overrides) ride in via the merged Laminas/Mezzio config — no in-band purge signal on the request path.

Install

composer require contenir/cache-laminas-mvc

The Module is auto-registered by laminas/laminas-component-installer.

Configure

Point the listener at a Laminas cache storage service ID, declare the event-manager identifiers/events to attach to, and (optionally) defaults plus per-route overrides:

// config/autoload/pagecache.global.php

use Contenir\Cache\Laminas\Mvc\Listener\CacheStrategy;

return [
    'pagecache' => [
        // Service ID resolving to a Laminas\Cache\Storage\StorageInterface.
        'cache'   => 'cache.pagecache',

        // Default per-request options. The `cache` flag is the master
        // enable switch — admin's pagecache.local.php overrides it
        // without touching siblings.
        'options' => [
            'cache'              => true,
            'cache_with_query'   => true,
            'cache_with_session' => false,
            'ttl'                => 600,
        ],

        // Optional regex => options-overrides.
        'routes'  => [
            '/api.*' => ['cache' => false],
        ],
    ],

    // Shared-event-manager attachments. The keys are SharedEventManager
    // identifiers (typically Application::class); the values are
    // event-name => priority pairs. Event names map to listener methods
    // via `'on' . ucwords($event)` — so 'dispatch' → onDispatch,
    // 'finish' → onFinish.
    'events' => [
        CacheStrategy::class => [
            \Laminas\Mvc\Application::class => [
                'dispatch' => -100,
                'finish'   =>  100,
            ],
        ],
    ],
];

A separate pagecache.local.php (written by the admin) is merged on top in the standard Laminas config-aggregator order, so the operator's defaults are preserved when the admin flips the master toggle.

The Module attaches the listener for you on bootstrap — there's nothing to wire in your Site's own Application\Module.

Optional: auth-aware cache keys

If the Site has authenticated frontend users and a cached page should not be shared between roles, register a service for Laminas\Authentication\AuthenticationServiceInterface. The factory will pull it via setAuthenticationService() and the role identifier will be mixed into the cache key. Without it, the role-suffix branch silently no-ops — fine for purely-public sites.

CSRF-aware caching

A page that renders a Laminas\Form\Element\Csrf token is per-user and must not be cached — the token is bound to the user's session, and a cached HTML page would replay one user's token to the next.

When laminas/laminas-form is installed, the package's ConfigProvider registers a delegator on the FormElement view helper that fires CacheStrategy::EVENT_DISABLE whenever a Csrf element is rendered. The listener attaches to that event on the same identifier(s) it uses for dispatch/finish; on receipt it flips an internal disabled flag, and onFinish skips storage. Pages with forms render normally; only the caching of those pages is suppressed.

To opt out:

// config/autoload/pagecache.local.php
return [
    'pagecache' => [
        'disable_on_csrf' => false,
    ],
];

When disable_on_csrf is false the delegator returns the original FormElement helper untouched (no overhead, no event firing).

For non-Laminas-form CSRF rendering, or any other reason a page must opt out at runtime, fire the event yourself from anywhere in the request lifecycle:

$em->trigger(\Contenir\Cache\Laminas\Mvc\Listener\CacheStrategy::EVENT_DISABLE);

…or grab the listener service and call disable() directly.

How it works

Listener\CacheStrategy typically attaches to MvcEvent::EVENT_DISPATCH (early) and EVENT_FINISH (late). On the inbound pass it builds the cache key from the configured request signals, returns a stored response when one exists, and short-circuits dispatch. On the outbound pass it stores the final response when the active options say to cache it.

pagecache.options.cache = false disables the listener entirely for the request — useful as an admin-controlled kill switch and as a per-route override for endpoints that must never be cached.

CacheStrategy::EVENT_DISABLE ('pagecache.disable') lets per-render opt-out signals reach the listener: anything in the request that knows the response is not safe to cache (CSRF tokens, flash messages, authenticated banners) can fire the event and the listener will short-circuit onFinish for that request.

What's in the cache key

The key is md5() of:

  1. Host$request->getUri()->getHost(). Multi-host deployments never cross-pollute.
  2. Path$request->getUri()->getPath().
  3. Accept-Encoding request header value — so a gzipped response stored against a gzip-accepting client is never served to a client that didn't advertise gzip support.
  4. Authenticated role suffix$identity->getRoleId() when an AuthenticationServiceInterface service is registered and an identity is present. No service registered ⇒ this branch no-ops (fine for purely-public sites).
  5. Superglobal hashesmd5(serialize($vars)) for each of query, post, files, cookie whose make_id_with_* flag is true. Whose presence with cache_with_* set false short-circuits caching entirely for the request.

Anything not in this list — User-Agent, Referer, custom X-* headers, third-party tracking cookies your app never reads — is invisible to the cache by design. The cache assumes the response is a pure function of the inputs above. If a controller varies its response on something outside that set (e.g. UA-sniffing for mobile markup) without keying on it, that's a poisoning bug in the controller, not the cache.

What's never cached

The listener short-circuits in onDispatch for any of:

  • non-GET/HEAD request methods (so file-upload POSTs don't even buffer through the cache layer)
  • Range: request header present (don't cache 206 partial responses as if they were full)
  • Authorization: request header present (per-user credentials ⇒ per-user response)

…and in onFinish for any response with a status code other than 200 OK (catches 304, 301/302 redirects, 404/5xx errors).

These are unconditional — there is no config flag to turn them off. If you have a route that genuinely needs to cache a non-200 response, that's a different design problem than this listener is built for.

Purging

Purging is not this listener's responsibility. Admin tooling that wants to clear cached pages (or specific keys) talks to the same cache storage backend directly — the Site config tells it which adapter the listener is wrapping.

contenir/cache-laminas-mvc 适用场景与选型建议

contenir/cache-laminas-mvc 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 57 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 05 月 08 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 contenir/cache-laminas-mvc 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 contenir/cache-laminas-mvc 我们能提供哪些服务?
定制开发 / 二次开发

基于 contenir/cache-laminas-mvc 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 57
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 45
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-05-08