mattferris / staccato
原生PHP模板的最简模板库
This package is auto-updated.
Last update: 2024-08-29 23:33:32 UTC
README
Staccato 是一个用于原生PHP模板的最简模板系统。
它借鉴了令人尊敬的 Twig 的基础思想,主要是继承模型。因此,它建立在通过 块 扩展模板的概念之上。提供缓存作为一等特性(尽管不是必需的),支持 动态 缓存,允许缓存的模板包含动态内容。简单的插件设施确保 Staccato 可以按需扩展。Staccato 内置了一个 markdown 插件,它使用 Parsedown。
继承
你有想倾诉的事情吗?创建一个博客!从编写一个简单的网站模板 base.tmpl.php
开始。
<!doctype html> <html> <head> <meta charset="utf-8"> <title>The Frivolous Fancies of Feral Foxes</title> <link rel="stylesheet" type="text/css" href="blog.css"> </head> <body> <header><h1>The Frivolous Fancies of Foxes</h1</header> <article> <!-- content goes here --> </article> </body> </html>
太棒了!现在让我们考虑如何包含内容。在渲染时,模板可以传递变量。这让我们可以使用变量向模板提供内容。我们只需要在模板中的 <article>
标签中输出变量。
<article> <header><h1><?= $title ?></h1></header> <?= $body ?> </article>
有一个内置变量叫做 $_
,它指的是代表当前模板的 Template 实例。它的使用将在后面介绍。
现在我们可以渲染模板了。
use MattFerris\Staccato\Staccato; $vars = [ 'title' => 'Are Foxes Funny or Frightening?', 'body' => '...'; ]; echo (new Staccato())->render('base.tmpl.php', $vars);
当然,我们到目前为止所做的一切都是标准的PHP模板,不需要模板引擎。所以让我们让事情变得有趣。
随着读者群体的增长,你开始注意到对特定类型内容的需求,如评论和更正式的文章,除了当前的非正式帖子。是时候扩展你的模板以为每种类型的内容创建独特的样式了。 块 使这一点变得相当容易。
<?php namespace MattFerris\Staccato ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>The Frivolous Fancies of Feral Foxes</title> <link rel="stylesheet" type="text/css" href="blog.css"> </head> <body> <header><h1>The Frivolous Fancies of Foxes</h1</header> <article> <?php begin($_, 'content') ?> <?php end($_) ?> </article> </body> </html>
首先,我们使用 Staccato 函数 begin()
定义了一个名为 content
的块。所有 Staccato 函数都需要你传递模板实例作为它们的第一个参数。实例作为 $this
或我们之前介绍的更简单的 $_
可用。 begin()
还需要你传递一个块名称,在这种情况下为 content
。最后,块通过 end()
终止。
那些细心的读者也会注意到我们为这个模板指定了一个命名空间 MattFerris\Staccato
。这是为了提供方便访问模板函数。否则,您将不得不指定完全限定的函数名称(例如 <?php MattFerris\Staccato\begin($_, 'content') ?>
)。谢谢!
接下来,我们可以定义一个名为 article.tmpl.php
的模板,它将扩展我们的基本模板。
<?php namespace MattFerris\Staccato ?> <?php extend($_, 'base.tmpl.php') ?> <?php begin($_, 'content') ?> <header><h1><?= $title ?></h1></header> <?= $body ?> <?php end($_) ?>
我们可以使用 extend()
函数扩展 base.tmpl.php
。通过这样做,我们可以访问在 base.tmpl.php
中定义的块。扩展是通过修改父模板中块的内容来完成的。在扩展块中定义的任何内容都将覆盖父模板中定义的内容。
文章需要自己的样式表。所以让我们在 base.tmpl.php
中定义一个用于样式表的块,并将现有的样式表添加到其中。
<head> <meta charset="utf8"> <title>The Frivolous Fancies of Feral Foxes</title> <?php block($_, 'css') ?> <link rel="stylesheet" type="text/css" href="blog.css"> <?php end($_) ?> </head>
现在我们可以在 article.tmpl.php
中访问 css
块。
<?php block($_, 'css') ?> <link rel="stylesheet" type="text/css" href="article.css"> <?php end($_) ?>
但是,一旦我们扩展了 css
块,我们将覆盖父模板并丢失 base.css
样式表。幸运的是,我们可以使用 parent()
访问父块的内容。
<?php block($_, 'css') ?> <?= parent($_) ?> <link rel="stylesheet" type="text/css" href="article.css"> <?php end($_) ?>
然而,因为我们只是向块中追加样式表,我们可以使用快捷方式。
<?php append($_, 'css) ?> <link rel="stylesheet" type="text/css" href="article.css"> <?php end($_) ?>
append()
函数将扩展一个块,使其内部定义的所有内容都追加到父内容中。同样,prepend()
可以用于将内容追加到父块中。
模板包含
时不时地,你会发布一系列相关的博客文章、评论或文章。为了提高可用性,你希望在组成系列的页面中添加一些系列导航元素。这意味着你不能简单地将导航元素添加到你的基本模板中。你也不希望为每个子模板(例如article.tmpl.php
)分别实现。这时就出现了incl()
函数,它允许你将一个模板的渲染内容包含到另一个模板中。我们可以创建一个名为series-nav.tmpl.php
的模板,内容如下。
<?php namespace MattFerris\Staccato ?> <nav> <ul> <li><a href="<?= $prev ?>">Previous</a></li> <li><a href="<?= $next ?>">Next</a></li> </ul> </nav>
现在我们可以在article.tmpl.php
中包含这个模板。
<?php begin($_, 'content') ?> <?= incl($_, 'series-nav.tpl.php', [ 'prev' => '...', 'next' => '...' ]) ?> <header><h1><?= $title ?></h1></header> <?= $body ?> <?php end($_) ?>`
注意,incl()
函数返回模板内容作为字符串,因此必须手动输出。
缓存
虽然模板原生支持缓存,但直到你启用缓存插件,你才能利用这一功能。
use MattFerris\Staccato\Staccato; use MattFerris\Staccato\Plugins\Cache\FileCache; use MattFerris\Staccato\Plugins\Cache\CachePlugin; $path = 'cache/dir'; // path to a directory to store cache entries $ttl = 3600; // keep cache entries for one hour $cache = new FileCache('path/to/cache/dir', $ttl); $staccato = (new Staccato()) ->addPlugin(new CachePlugin($cache));
一旦启用,模板将自动缓存其渲染内容。所有后续对模板的请求将返回缓存的模板,直到缓存条目过期或被删除。
可以使用set()
函数禁用模板的缓存。
<?php namespace MattFerris\Staccato ?> <?php set($_, 'cachemode', 'disabled') ?>
cachemode
可以是static
(默认)、dynamic
(见下文)或disabled
。
缓存块
当模板被渲染时,cache块将缓存其内容。即使模板被重新渲染,它也会使用缓存块,直到它过期或被删除。这对于计算成本高昂的内容非常有用。
<?php cache($_, 'myblock', $ttl) ?> <?= some_expensive_operation() ?> <?php end($_) ?>
cache
接受一个第三个参数,指定缓存数据有效的时长(以秒为单位)。为了最大限度地利用缓存块,TTL应该设置得大于模板的TTL。TTL默认为1小时(3,600秒),而缓存块可以设置为1天(86,400秒),甚至1周(604,800秒)。
注意,可以使用begin()
、append()
和prepend()
扩展缓存块。但是,不能使用cache()
扩展标准块。当然,任何扩展缓存块的块都将缓存扩展块的内容。
无论模板的缓存模式设置为何,cache()
都会缓存块的内容。
缓存包含
可以使用cincl()
包含模板,这将返回包含模板的缓存内容。与cache()
一样,cincl()
也接受TTL作为第三个参数。并且与cache()
一样,cincl()
提供了对渲染成本高昂的模板进行缓存的另一选项。
<?= cincl($_, 'template.tmpl.php', $ttl) ?>
无论当前模板和包含模板的缓存模式设置为何,cincl()
都会缓存包含模板的内容。
缓存获取的内容
从远程URL获取内容可能既昂贵又耗时。在远程内容不经常变化的情况下,可以使用cfetch()
来缓存获取的内容。cfetch()
使用file_get_contents()
执行请求,因此你可以使用它支持的任何协议。
<?= cfetch($_, 'https://example.com/expensive/api/call', $ttl) ?>
非缓存获取
ncfetch()
允许你在缓存模板中包含动态获取的内容。使用ncfetch()
将自动将模板的缓存模式设置为dynamic
。使用动态缓存的模板实际上是编译的。编译的模板包含指示解析器如何获取远程内容的标签。远程内容替换标签,并返回结果。虽然动态缓存的模板仍然经历少量处理,但这种权衡使得可以最大限度地利用模板。
<?= ncfetch($_, 'https://example.com/feed') ?>
Markdown
Markdown功能通过Markdown插件提供。该插件引入了一个markdown块,它在模板渲染时将内容解析为markdown,以及一个md()
函数,它将字符串解析为markdown。
添加插件。
use MattFerris\Staccato\Staccato; use MattFerris\Staccato\Plugins\Markdown\MarkdownPlugin; $staccato = (new Staccato()) ->addPlugin(new MarkdownPlugin());
然后在模板中开始解析Markdown。
<?php namespace MattFerris\Staccato ?> <?php markdown($_, 'body') ?> Article Title ============= This is an *article* about *stuff*! <?php end($_) ?> <?= md($_, 'You shall not *pass*!') ?>