snicco/templating 问题修复 & 功能扩展

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

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

snicco/templating

Composer 安装命令:

composer require snicco/templating

包简介

Provides a unified API for various templating engines.

README 文档

README

codecov Psalm Type-Coverage Psalm level PhpMetrics - Static Analysis PHP-Versions

The Templating component of the Snicco project provides a simple, object-oriented API around popular PHP template engines.

Table of contents

  1. Installation
  2. Usage
    1. Overview
    2. Creating a view
    3. Directly render a view
    4. Finding the first existing view
    5. Referencing nested directories
    6. Global context / View composers
    7. View factories
    8. The PHPViewFactory
      1. Instantiation
      2. Template inheritance
  3. Contributing
  4. Issues and PR's
  5. Security

Installation

composer require snicco/templating

Usage

This package consists of the following main components:

  • An immutable View object, which can be rendered to its string representation with a given context.
  • The TemplateEngine, which is a facade class used to create and render View objects.
  • The ViewFactory interface, which abstracts away implementation details of how a View instance is rendered. See Using view factories;
  • The ViewContextResolver, which is responsible for adding global context and view composer context to a view that is being rendered.

The following directory structure is assumed for the examples in this README:

your-project-root
├── templates/
│   ├── users/                 
│   │   ├── profile.php  
│   │   └── ...
│   └── hello-world.php             
└── ...
// ./templates/hello-world.php

echo "Hello $first_name";

Creating a view

An instance of View is always created by a call to TemplateEngine::make().

Context can be added to a View instance which will be available to the underlying template once the View is rendered.

use Snicco\Component\Templating\TemplateEngine;

// The TemplateEngine accepts one or more instances of ViewFactory.
// See #Using view factories for available implementations.
$view_factory = /* */ 

$engine = new TemplateEngine($view_factory);

// hello-world is relative to the root directory "templates"
$view = $engine->make('hello-world');

$view1 = $view->with('first_name', 'Calvin');
$output = $engine->renderView($view1);
var_dump($output); // Hello Calvin

$view2 = $view->with('first_name', 'Marlon');
$output = $engine->renderView($view2);
var_dump($output); // Hello Marlon

// Views can also be created by passing an absolute path
$view = $engine->make('/path/to/templates/hello-world.php');

Directly rendering a view

If you want to render a template right away you can use the render method on the TemplateEngine.

use Snicco\Component\Templating\TemplateEngine;

$view_factory = /* */ 

$engine = new TemplateEngine($view_factory);

$output = $engine->render('hello-world', ['first_name' => 'Calvin']);
var_dump($output); // Hello Calvin

Finding the first existing view

Both the make and render method of the TemplateEngine accept an array of strings in order to use the first existing view.

use Snicco\Component\Templating\TemplateEngine;

$view_factory = /* */ 

$engine = new TemplateEngine($view_factory);

$view = $engine->make(['hello-world-custom', 'hello-world']);

$output = $engine->render(['hello-world-custom', 'hello-world'], ['first_name' => 'Calvin']);
var_dump($output); // Hello Calvin

If no view can be found, a ViewNotFound exception will be thrown.

Referencing nested directories

Both the make and render method of the TemplateEngine will expand dots to allow directory traversal. This works independently of the concrete ViewFactory that is being used.

use Snicco\Component\Templating\TemplateEngine;

$view_factory = /* */ 

$engine = new TemplateEngine($view_factory);

$view = $engine->make('users.profile');

$output = $engine->render('users.profile', ['first_name' => 'Calvin']);

Global context / View composers

Before a view is rendered, it's passed to the ViewContextResolver, which is responsible for applying:

  1. global context that should be available in all views
  2. context provided by view composers to some views

A view composer can be a Closure or class that implements ViewComposer.

The ViewContextResolver will be needed to instantiate the concrete implementations of the view factory interface.

Adding global context:

use Snicco\Component\Templating\Context\ViewContextResolver;
use Snicco\Component\Templating\Context\GlobalViewContext;

$global_context = new GlobalViewContext()

// All templates now have access to a variable called $site_name
$global_context->add('site_name', 'snicco.io');

// The value can be a closure which will be called lazily.
$global_context->add('some_var', fn() => 'some_value');

$context_resolver = new ViewContextResolver($global_context);

If you pass an array as the second argument to GlobalViewContext::add you can reference nested values in your views like so:

use Snicco\Component\Templating\Context\ViewContextResolver;
use Snicco\Component\Templating\Context\GlobalViewContext;

$global_context = new GlobalViewContext()
$global_context->add('app', [
   'request' => [
       'path' => '/foo',
       'query_string' => 'bar=baz'
   ]
]);

// Inside any template
echo $app['request.path']
echo $app['request.query_string']

Adding view composers:

$context_resolver = /* */

// Using a closure
$context_resolver->addComposer('hello-world', fn(View $view) => $view->with('foo', 'bar'));

// Using a class that implements ViewComposer
$context_resolver->addComposer('hello-world', HelloWorldComposer::class);

// Adding a composer to multiple views
$context_resolver->addComposer(['hello-world', 'other-view'], fn(View $view) => $view->with('foo', 'bar'));

// Adding a composer by wildcard
// This will make the current user available to all views inside the templates/users directory.
$context_resolver->addComposer('users.*', fn(View $view) => $view->with('current_user', Auth::user()));

Using view factories

All view factories implement the ViewFactory interface.

They are used by the TemplateEngine and contain the underlying logic to render a View instance to its string representation.

It's possible to use multiple view factories together in which case the first factory that can render a given View will be used.

The following view factories are currently available:

  • PHPViewFactory, included in this package. A bare-bones implementation that works great for small projects with only a handful of views.
  • BladeViewFactory, included in a separate package. Integrates Laraval's Blade as a standalone template engine with this package, while retaining all features of both.
  • TwigViewFactory - coming soon.

The PHPViewFactory

The PHPViewFactory is a bare-bones implementation that is great for small projects where you might only have a handful of views.

Instantiation

The PHPViewFactory takes a ViewContextResolver as the first argument and an array of root template directories as the second argument.

If a view exists in more than one template directory, the first matching one will be used. This is great for allowing certain templates to be overwritten by templates in another (custom) template directory.

use Snicco\Component\Templating\TemplateEngine;
use Snicco\Component\Templating\ViewFactory\PHPViewFactory;

$context_resolver = /* */

$php_view_factory = new PHPViewFactory(
    $context_resolver, 
    [__DIR__.'/templates']
);

$template_engine = new TemplateEngine($php_view_factory);

Template inheritance

The PHPViewFactory allows for very basic template inheritance.

Assuming that we have the following two templates:

<?php
// post.php

/*
 * Extends: post-layout
 */

echo "Post one content"
<?php
// post-layout.php
?>
<html lang="en">

    <head>
        Head content goes here
        <title><?= htmlentities($title, ENT_QUOTES, 'UTF-8') ?></title>
    </head>
    <body>
        <main>
            <?= $__content ?>
        </main>
        
        <footer>
            Footer content goes here
        </footer>
    </body>
</html>

Rendering the post view will yield:

$template_engine->render('post', ['title' => 'Post 1 Title']);
<html lang="en">

<head>
    Head content goes here
    <title>Post 1 Title</title>
</head>
<body>
<main>
    Post one content
</main>

<footer>
    Footer content goes here
</footer>
</body>

</html>

A couple of things to note:

  • The parent template is indicated by putting Extends: parent-view-name inside /* */ comments within the first 100 bytes of the template.
  • Context that is passed to a child view is available to the parent view.
  • The parent view can output the child-content by using the $__content variable.
  • Nested inheritance is possible. post-layout.php could for example extend layout.php

Contributing

This repository is a read-only split of the development repo of the Snicco project.

This is how you can contribute.

Reporting issues and sending pull requests

Please report issues in the Snicco monorepo.

Security

If you discover a security vulnerability, please follow our disclosure procedure.

snicco/templating 适用场景与选型建议

snicco/templating 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 16.61k 次下载、GitHub Stars 达 0, 最近一次更新时间为 2022 年 04 月 17 日, 在 PHP 生态内属于活跃度较高的组件。

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

围绕 snicco/templating 我们能提供哪些服务?
定制开发 / 二次开发

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

BUG 修复 & 性能优化

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

项目外包 & 长期维护

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

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

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: LGPL-3.0-only
  • 更新时间: 2022-04-17