In part one of this two-part series I started looking at FigDice, a PHP templating system that takes a slightly different approach to most.
在这个由两部分组成的系列文章的第一部分中,我开始研究了FigDice ,这是一个PHP模板系统,大多数情况下采用的方法略有不同。
![Figs fruits](https://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2014/11/1415476871Fotolia_61934758_Subscription_Monthly_M-Small.jpg)
So far we’ve put together a very simple example website using Figdice. We’ve implemented a couple of pages, a Twitter feed and some template partials.
到目前为止,我们已经使用Figdice整理了一个非常简单的示例网站。 我们已经实现了几个页面,一个Twitter feed和一些模板部分。
In this second and final part we’re going to add a simple blog to our example site, which allows us to look in more detail at Figdice’s concept of data feeds. We’ll also look at internationalization, translating some of the site’s content into a couple of additional languages.
在第二部分(也是最后一部分)中,我们将向示例站点添加一个简单的博客,该博客使我们可以更详细地了解Figdice的数据馈送概念。 我们还将研究国际化,将网站的某些内容翻译成几种其他语言。
代码 (The Code)
I’ve created a separate repository for the code for this second part of the series, which you’ll find on Github. It expands upon the code we wrote in Part One.
我已经为该系列第二部分的代码创建了一个单独的存储库,您可以在Github上找到它 。 它扩展了我们在第一部分中编写的代码。
There’s also an online demo.
还有一个在线演示 。
建立一个简单的博客 (Building a Simple Blog)
Now let’s create a more complex example of a data feed, by implementing a simple blog.
现在,通过实现一个简单的博客,创建一个数据馈送的更复杂的示例。
First, create another feed class – this time for a blog.
首先,创建另一个供稿类–这次是博客。
<?php namespace Sitepoint\Feed;
use figdice\Feed;
class BlogFeed extends Feed
{
public function run() {
return array(
array(
'id' => 3,
'slug' => 'post-three',
'title' => 'Sample Blog Post Three',
'body' => '<p>Donec sed odio dui. Maecenas sed diam eget risus varius blandit sit amet non magna. Aenean lacinia bibendum nulla sed consectetur. Vestibulum id ligula porta felis euismod semper. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>',
'author' => array(
'id' => 1,
'name' => 'Bob',
),
'created' => 12345,
),
// .. more posts here, omitted for brevity
);
}
}
Again, we’re faking the data, but retrieving blog posts from sort of storage is the sort of thing which is covered extensively elsewhere and ought to be relatively straightforward.
同样,我们伪造数据,但是从某种存储中检索博客文章是一种在其他地方广泛讨论的事情,应该相对简单。
Now modify the FeedFactory
class, letting it know about our new feed:
现在修改FeedFactory
类,让它知道我们的新feed:
// ...
use Sitepoint\Feed\BlogFeed;
class FeedFactory implements \figdice\FeedFactory
{
// ...
public function create($className, array $attributes) {
if ($className == 'BlogFeed') {
return new BlogFeed();
}
if ($className == 'TwitterFeed') {
return new TwitterFeed();
}
// ...
}
}
Now create a new view, which we’ll use for our blog listing:
现在创建一个新视图,我们将其用于博客清单:
<!-- file: blog.html -->
<?xml version="1.0" encoding="utf-8"?>
<fig:template xmlns:fig="http://figdice.org/">
<fig:dictionary file="menu.xml" name="menu" />
<fig:feed class="BlogFeed" target="posts" />
<fig:include file="layout.html" />
<title fig:plug="docTitle"><fig:trans dict="menu" key="blog" /></title>
<h1 fig:plug="pageTitle"><fig:trans dict="menu" key="blog" /></h1>
<div fig:plug="pageContent">
<article fig:walk="posts">
<h2>
<a href="/blog/post/{slug}" fig:text="title"></a>
</h2>
<p class="author">By <span fig:text="author/name" /></p>
<div fig:text="body"></div>
<hr fig:auto="true" />
</article>
</div>
</fig:template>
Much of this we’re already seen, but let’s look at the fig:walk
bit. This time, instead of creating a simple list element and injecting a single property, we’re creating additional markup; in this case, for each post we’re creating an <article>
element.
我们已经看到了很多内容,但让我们看一下fig:walk
位。 这次,我们创建了附加的标记,而不是创建一个简单的list元素并注入单个属性。 在这种情况下,我们为每个帖子创建一个<article>
元素。
Once we’re in a “walk” loop – which is essentially an iterator – properties can be accessed by name; see the <div fig:text="body"></body>
for example.
一旦进入“遍历”循环(本质上是一个迭代器),就可以按名称访问属性。 例如,请参见<div fig:text="body"></body>
。
Within the <h2>
tag, we create a link by using fig:text
to insert the title of the blog post inside the <a>
tag, and use curly brackets {slug}
to incorporate the post’s slug into the URL (href) attribute.
在<h2>
标记内,我们使用fig:text
在<a>
标记内插入博客文章的标题,并使用大括号{slug}
将帖子的词条合并到URL(href)属性中,从而创建链接。 。
The link within the <h2>
tag is slightly more complicated, because we’re defining an expression which will get evaluated. It concatenates the string /blog/post/
with the value of the post’s slug
attribute to generate a URL, e.g. /blog/post/post-three
.
<h2>
标记内的链接稍微复杂些,因为我们正在定义一个将被求值的表达式。 它将字符串/blog/post/
与post的slug
属性的值连接起来以生成URL,例如/blog/post/post-three
。
You can also access deeper properties using slashes. For the author information we want to extract the name
property from the author
; so we use <span fig:text="author/name" />
. You can also use the double-dot (..
) notation to go up a level.
您还可以使用斜杠访问更深的属性。 对于作者信息,我们要从author
提取name
属性; 因此我们使用<span fig:text="author/name" />
。 您也可以使用双点( ..
)表示法来升级一个级别。
<fig:dictionary>
and <fig:trans>
are used for internationalization, which we’ll look at shortly.
<fig:dictionary>
和<fig:trans>
用于国际化,我们将在稍后介绍。
提要和属性 (Feeds and Attributes)
You might remember there was a second, optional parameter to the factory’s create
method. If you add any addtional attributes to the fig:feed
element that aren’t in the fig
namespace, class
or target
, they get passed to the factory as that second attribute.
您可能还记得工厂的create
方法还有另一个可选参数。 如果您向fig:feed
元素添加不在fig
名称空间, class
或target
中的任何其他属性,它们将作为第二个属性传递给工厂。
For example, you could modify blog.html
as follows:
例如,您可以按以下方式修改blog.html
:
<fig:feed class="BlogFeed" target="posts" num-posts="5" sort="'date'" sort-direction="'asc'" />
Note the single quotes inside the double-quotes; this is because the values are evaluated.
注意双引号内的单引号; 这是因为评估了值。
Then, in your factory, you can use getParameter()
– or if you know what type to expect, getParameterBool()
/ getParameterInt()
/ getParameterString()
. Each of these methods takes a default as an optional second parameter.
然后,在工厂中,可以使用getParameter()
–或者,如果知道所需的类型,请使用getParameterBool()
/ getParameterInt()
/ getParameterString()
。 这些方法中的每一个都将默认值作为可选的第二个参数。
So for this example, we could extend the factory like this:
因此,对于此示例,我们可以像这样扩展工厂:
// @file FeedFactory.php
public function create($className, array $attributes) {
$num_posts = $this->getParameterInt('num-posts', 10);
$sort_by = $this->getParameterString('sort', 'date');
$sort_dir = $this->getParameterString('sort-direction', 'desc');
// now you can use these values, for example when you instantiate the feed
See the feeds section of the manual for more details.
有关更多详细信息,请参见手册的提要部分 。
整理博客 (Wrapping up the Blog)
Now that we’ve implemented a simple blog listing, we need to create a page to display an individual blog post.
现在,我们已经实现了一个简单的博客列表,我们需要创建一个页面来显示单个博客文章。
First, let’s define the route:
首先,让我们定义路线:
// Individual blog posts.
$app->get('/blog/post/{slug}', function($slug) use ($view) {
$view->loadFile( '../templates/post.html' );
// We use mount to "inject" the slug into the view, which it can then use to "pull" the appropriate post.
$view->mount('slug', $slug);
return $view->render();
});
Notice how we’re injecting the slug – which is a URL parameter – into the view using the mount()
method.
请注意,我们如何使用mount()
方法将Slug(这是一个URL参数)注入视图中。
Now let’s create the view:
现在让我们创建视图:
// post.html
<xml fig:mute="true"> <!-- Mute because this tag should not end up in the HTML document. But the FigDice template must have an XML root node. -->
<fig:dictionary file="menu.xml" name="menu" />
<!-- Load the page layout -->
<fig:include file="layout.html" />
<fig:feed class="BlogFeed" target="post" post-slug=" /slug " />
<!-- Set the <title> tag -->
<title fig:plug="docTitle"><fig:trans dict="menu" key="about" /></title>
<!-- Set the <h1> tag -->
<h1 fig:plug="pageTitle" fig:text="/post/title" />
<!-- "Plug in" the page content -->
<div fig:plug="pageContent">
<p class="back"><a href="/blog">« <fig:trans dict="menu" key="blog" /></a></p>
<p class="author">By <span fig:text="/post/author/name" /></p>
<div fig:text="/post/body"></div>
</div>
</xml>
Much of this should be familiar, but let’s look at the <fig:feed>
element more closely:
其中许多应该是熟悉的,但让我们更仔细地看一下<fig:feed>
元素:
<fig:feed class="BlogFeed" target="post" post-slug=" /slug " />
Notice how we’re feeding the “slug” variable, which we’ve made available to the view using the mount()
method, back to the BlogFeed class by using the post-slug
attribute.
请注意,我们如何使用mount()
方法将“ slug”变量提供给视图,并使用post-slug
属性将其返回给BlogFeed类。
Let’s modify the BlogFeed class to retrieve a single blog post. Because we’re defining posts as a simple array, place this after we instantiate it:
让我们修改BlogFeed类以检索单个博客文章。 由于我们将帖子定义为一个简单的数组,因此请在实例化之后将其放置:
$posts = array( .... );
// Get the slug, if provided
$slug = $this->getParameterString('post-slug');
if ($slug) {
// Use a little Underscore magic to retrieve the appropriate post
$post = Arrays::find($posts, function($post) use ($slug) {
return ($post['slug'] == $slug);
});
return $post;
} else {
// No slug, we want the lot.
return $posts;
}
Obviously in a “real” application you’d do some sort of database lookup, but this example should give you an idea of how to set up a data feed for your views.
显然,在“真实”应用程序中,您将进行某种数据库查找,但是此示例应使您了解如何为视图设置数据源。
条件 (Conditions)
A quick note on conditionals, which you can achieve using the fig:cond
attribute.
关于条件的简要说明,您可以使用fig:cond
属性来实现。
For example, to show some content given a certain condition:
例如,在给定条件下显示一些内容:
<span fig:cond="logged_in == true">You are logged in</span>
To add a class to an <article>
if it’s published:
要将类添加到<article>
如果已发布):
<article>
<fig:attr fig:cond="status == 1" name="class">published</fig:attr>
...
</article>
If status is set to one, the resulting HTML will be as follows:
如果状态设置为1,则结果HTML将如下所示:
<article class="published">
...
</article>
国际化 (Internationalization)
FigDice makes translating text in your templates easy. Let’s start by creating some language files to hold our translatable strings. In a large application you might want to create a file per module, making it easy to re-use them across multiple applications.
FigDice使翻译模板中的文本变得容易。 让我们首先创建一些语言文件来保存我们的可翻译字符串。 在大型应用程序中,您可能希望为每个模块创建一个文件,从而可以轻松地在多个应用程序中重复使用它们。
A typical structure might look like this:
典型的结构可能如下所示:
lang
en
menu.xml
products.xml
checkout.xml
es
menu.xml
products.xml
checkout.xml
fr
menu.xml
products.xml
checkout.xml
Let’s create a concrete example, by translating our example site’s menu:
让我们通过翻译示例站点的菜单来创建一个具体示例:
<!-- lang/en/menu.xml -->
<fig:dictionary xmlns:fig="http://www.figdice.org/" language="en">
<entry key="home">Home</entry>
<entry key="about">About</entry>
<entry key="blog">Blog</entry>
</fig:dictionary>
Then, the Spanish version of this file:
然后,此文件的西班牙语版本:
<!-- lang/es/menu.xml -->
<fig:dictionary xmlns:fig="http://www.figdice.org/" language="es">
<entry key="home">Inicio</entry>
<entry key="about">Acerca</entry>
<entry key="blog">Blog</entry>
</fig:dictionary>
When you want to use translated text, first reference the dictionary file and give it an identifier somewhere in your template:
如果要使用翻译的文本,请首先引用字典文件,并在模板中的某个位置为其提供标识符:
<fig:dictionary file="menu.xml" name="menu" />
Now you can insert the value of an item using the dictionary’s key – taken from the name
attribute in the fig:dictionary
declaration – and the text item’s key
:
现在,您可以使用字典的键(从fig:dictionary
声明中的name
属性获取)和文本项的key
插入项目的值:
// file: templates/menu.html
<ul class="nav nav-pills pull-right">
<li><a href="/"><fig:trans dict="menu" key="home" /></a></li>
<li><a href="/about"><fig:trans dict="menu" key="about" /></a></li>
<li><a href="/blog"><fig:trans dict="menu" key="blog" /></a></li>
</ul>
Now, somewhere in your application code, tell the view where to find your language files:
现在,在应用程序代码中的某处,告诉视图在哪里可以找到您的语言文件:
$view->setTranslationPath('../lang');
Then set the language:
然后设置语言:
$view->setLanguage('es');
// or $view->setLanguage('en'), $view->setLanguage('fr'), etc
Let’s implement language-switching in our sample application, albeit keeping it really simple.
让我们在示例应用程序中实现语言切换,尽管实际上非常简单。
First, we’ll add some links in the header of the layout (templates/layout.html
):
首先,我们将在布局的标题( templates/layout.html
)中添加一些链接:
<a href="/lang/en"><img src="/img/en.png" width="16" height="16" /></a> | <a href="/lang/es"><img src="/img/es.png" width="16" height="16" /></a>
You’ll find the flag icons we’re using here in the sample repository.
您可以在示例存储库中找到我们正在使用的标志图标。
Now implement the corresponding route, which simply pops the appropriate language code in a session variable:
现在实现相应的路由,该路由仅在会话变量中弹出相应的语言代码:
$app->get('/lang/{lang}', function ($lang) use ($app) {
$app['session']->set('lang', $lang);
return $app->redirect('/');
});
Finally, near the top of index.php
:
最后,靠近index.php
的顶部:
// Get the language from the session, if it's set - default to English.
$language = $app['session']->get('lang', 'en');
// ...and set it.
$view->setLanguage($language);
Now if you browse the site, you should find that clicking one of the flags will switch the menu labels to the appropriate language.
现在,如果您浏览该站点,您应该发现单击标志之一会将菜单标签切换为适当的语言。
摘要 (Summary)
In these two articles I’ve introduced FigDice, a templating system which takes a very different approach to most. There’s more to it than I’ve been able to cover, so check out the manual, tutorials, examples or reference.
在这两篇文章中,我介绍了FigDice,这是一个模板系统,大多数情况下采用的方法都非常不同。 除了我已经介绍的内容之外,还有更多内容,因此请查看手册 , 教程 , 示例或参考 。
I expect that while some people will like the approach that FigDice takes, equally some won’t – so I’d be interested to hear your thoughts the comments.
我希望尽管有些人会喜欢FigDice所采用的方法,但同样有些人会不喜欢–因此,我很想听听您的意见。
翻译自: https://www.sitepoint.com/building-internationalized-blog-figdice/