定制 daun/statamic-cache-directives 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

daun/statamic-cache-directives

Composer 安装命令:

composer require daun/statamic-cache-directives

包简介

Parse conditional comments for dynamic fragments in cached Statamic pages

README 文档

README

Parse conditional HTML comment directives after Statamic has rendered a page, so cached pages can still include small dynamic fragments.

This package is a lightweight alternative to Statamic's nocache tag. It is useful for tiny auth-, role-, or request-dependent islands where you only need to keep or remove existing markup without the overhead of the nocache data/session pipeline.

It is implemented as a static caching replacer for Statamic's half-measure static cache.

Installation

Install the package via composer:

composer require daun/statamic-cache-directives

Registration

Enable the replacer in config/statamic/static_caching.php.

+ use Daun\StatamicCacheDirectives\CacheDirectiveReplacer;

  'replacers' => [
      CsrfTokenReplacer::class,
      NoCacheReplacer::class,
+     CacheDirectiveReplacer::class,
  ],

Usage

Wrap markup in conditional comments. Matching blocks are kept when their expression evaluates to true; otherwise they are removed from the response.

<!--[if logged_in]-->
  <a href="/account">Account</a>
<!--[endif]-->

<!--[if logged_out]>
  <a href="/login">Log in</a>
<![endif]-->

The second format follows the downlevel-hidden syntax for conditional comments.

Syntax

Expressions use Symfony Expression Language syntax.

If

<!--[if logged_in]-->
  <p>Visible to signed-in users.</p>
<!--[endif]-->

<!--[if logged_in]>
  <p>Visible to signed-in users, hidden if unprocessed.</p>
<![endif]-->

Unless

<!--[unless logged_in]-->
  <p>Visible to guests.</p>
<!--[endunless]-->

<!--[unless logged_in]>
  <p>Visible to guests, hidden if unprocessed.</p>
<![endunless]-->

Not

Use either ! or not.

<!--[if !logged_in]-->
  <a href="/login">Log in</a>
<!--[endif]-->

<!--[if not super]-->
  <p>Regular user content.</p>
<!--[endif]-->

And

Use and or &&.

<!--[if logged_in and super]-->
  <a href="/cp">Control Panel</a>
<!--[endif]-->

Or

Use or or ||.

<!--[if logged_out or super]-->
  <script src="/js/public-preview.js"></script>
<!--[endif]-->

Echo

Use echo to print a variable value. Echo directives can be standalone or block-style. Output is escaped for html contexts.

<a href="/account" data-cache="<!--[echo cache_status]-->">
  <!--[echo account_label]-->
</a>

<!--[echo cache_status]>Unknown<![endecho]-->

Raw

Use raw to print a variable value without escaping. Use this only for values you fully control as printing untrusted data with raw is an XSS vector.

<!--[raw safe_svg_icon]-->

<!--[raw safe_svg_icon]>Fallback<![endraw]-->

Combined expressions

Use parentheses to group subexpressions or override precedence.

<!--[if logged_out or (logged_in and super)]-->
  <a href="/preview">Preview tools</a>
<!--[endif]-->

<!--[if (logged_out or super) and has_preview]-->
  <a href="/preview">Preview tools</a>
<!--[endif]-->

<!--[if !(logged_in and super)]-->
  <p>Visible unless signed in as a super admin.</p>
<!--[endif]-->

Nested data and object methods

Use [] for array keys and . for object properties or methods.

<!--[if cart["totals"]["items"] > 0 and customer.canCheckout()]-->
  <a href="/checkout">Checkout (<!--[echo cart["totals"]["items"]]-->)</a>
<!--[endif]-->

Unknown variable names throw an InvalidArgumentException, so typos fail loudly.

Built-in variables

These variables are available by default and can be used in expressions:

  • logged_in: Current Statamic user is authenticated.
  • logged_out: Current Statamic user is not authenticated.
  • super: Current Statamic user is a super admin.

Authentication uses Statamic's configured control-panel guard: config('statamic.users.guards.cp').

Real-world examples

Seed frontend auth state

<script>
  window.app = window.app || {};
  window.app.authenticated = false;
</script>

<!--[if logged_in]-->
  <script>window.app.authenticated = true;</script>
<!--[endif]-->

Swap account navigation without nocache

<nav>
  <!--[if logged_in]-->
    <a href="/account">Account</a>
    <form method="POST" action="/logout">
      <button type="submit">Log out</button>
    </form>
  <!--[endif]-->

  <!--[if logged_out]-->
    <a href="/login">Log in</a>
    <a href="/register" class="button">Create account</a>
  <!--[endif]-->
</nav>

Show edit links to super admins

<!--[if super]-->
  <aside class="admin-tools">
    <a href="{{ edit_url }}">Edit this page</a>
    <a href="/cp/collections/pages">Pages</a>
  </aside>
<!--[endif]-->

Hide conversion prompts from signed-in users

<!--[unless logged_in]-->
  <section class="cta">
    <h2>Save your favourites</h2>
    <p>Create an account to keep this list across devices.</p>
    <a href="/register" class="button">Sign up</a>
  </section>
<!--[endunless]-->

Load admin-only JavaScript

<!--[if logged_in and super]-->
  <script type="module" src="/build/admin-overlay.js"></script>
<!--[endif]-->

Custom variables

Add your own variable names with the variables hook. Register the hook during application boot, for example in app/Providers/AppServiceProvider.php. Values can be scalar values, arrays, objects, or closures that are called when the variable is evaluated.

use Daun\StatamicCacheDirectives\CacheDirectiveReplacer;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        CacheDirectiveReplacer::hook('variables', function (array $variables, Closure $next) {
            $variables['editor'] = fn () => auth()->user()?->roles()->has('editor') ?? false;
            $variables['member'] = fn () => auth()->user()?->groups()->has('members') ?? false;
            $variables['has_cart'] = fn () => (bool) session('cart.items');
            $variables['in_uk'] = fn () => new \GeoIp2\Database\Reader()->city(request()->getClientIp())->country->isoCode === 'UK';

            return $next($variables);
        });
    }
}

Then use those variables in comments:

<!--[if editor]-->
  <a href="{{ edit_url }}">Edit</a>
<!--[endif]-->

<!--[if logged_out and has_cart]-->
  <p>Create an account before checkout to save your order history.</p>
<!--[endif]-->

<!--[if member]-->
  <a href="/members/downloads">Member downloads</a>
<!--[endif]-->

<!--[unless in_uk]-->
  <p>This feature is only available in the UK.</p>
<!--[endunless]-->

Disabling a response

If a response contains this marker anywhere, directive parsing is skipped for the whole response. Use it as a kill switch on routes that must never be processed (for example email or preview endpoints).

<!--[cache-directives-disable]-->

Ignoring a range

Wrap a section in ignore markers to leave it verbatim while the rest of the response is still parsed. Directives inside the range are not processed, and the wrapper comments are removed from the output. This is useful for fragments that legitimately contain conditional comments (for example Outlook <!--[if mso]> markup) or documentation showing directive syntax.

<!--[cache-directives-ignore]-->
  <!--[if mso]><table><tr><td>Outlook</td></tr></table><![endif]-->
<!--[cache-directives-endignore]-->

Warning

Both markers control directive processing, so they must never originate from untrusted, user-controlled content. See Security below.

Security

This replacer scans the entire cached HTML response for directive comments. Cached pages frequently contain user-generated content (comments, reviews, usernames, profile fields, reflected search queries, form echoes). If any of that content can contain the strings below, it can subvert directive processing:

  • <!--[cache-directives-disable]--> disables all directive processing for the page. An attacker who injects it can prevent auth-gated blocks such as <!--[if super]-->...<!--[endif]--> from being stripped, exposing that markup to every visitor.
  • <!--[cache-directives-ignore]--><!--[cache-directives-endignore]--> leaves an arbitrary range unprocessed, which can likewise expose auth-gated markup wrapped inside it.
  • <!--[if ...]--> / <!--[echo ...]--> markers let injected content pair with, hide, or reveal surrounding directive blocks.

To stay safe, strip or neutralize directive comments from user-controlled content before it is rendered into a cacheable page. For example, remove <!--[ sequences from user input, or escape them:

// When rendering untrusted values into a page, neutralize directive markers.
$safe = str_replace('<!--[', '<!--&#91;', $userContent);

Failure handling:

  • A directive that fails to evaluate (for example an unknown variable) is removed (fails closed) rather than throwing, so a single malformed or injected directive cannot break the whole page. The error is reported to your logger.
  • When app.debug is enabled (local/dev), the failure is rethrown instead, so template typos surface loudly during development.

License

MIT

统计信息

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

GitHub 信息

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

其他信息

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

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固