JLayout Improvements for Joomla! 3.2
本文介绍了 Joomla! 3.2 中新的 JLayout 功能。大部分更改都是针对提高系统对第三方开发者的灵活性。
一些历史背景
让我们用一个例子来说明:您有一些带有标签的文章,但联系人也有标签,分类也有标签...
在 JLayouts 之前的旧模板系统中(基本上我们仍然用于视图),要渲染这些内容,需要将相同的 HTML 渲染代码复制/粘贴到您希望显示标签的每个位置。嗯,这并不难,对吧?好吧,但是然后我们有一个错误,有人为内容修复了它,但是忘记了分类,然后有人添加了一个酷炫的功能,但只适用于联系人.....问题开始出现,系统变得更加难以维护。
Yannick Gaultier 贡献了 JLayouts 来解决这个问题。这是一个很棒、简单的系统,它背后的概念是可重用代码块,允许您从对象/数据数组中渲染 HTML。
使用布局的好处
感谢 JLayout 系统您可以使用以下方式渲染项目的标签:
echo JLayoutHelper::render('joomla.content.tags', $itemTags);
这将基本上将输出文件 /layouts/joomla/content/tags.php 的输出,将 $itemTags 作为参数传递给内部使用。这是我们以前在模块中做的事情,但现在以标准方式进行。唯一的要求是 $itemTags 对象对所有项目具有相同的结构。
那么,这有什么好处呢?
1. 可重用性
我们只需要维护一个布局。设计师只需要自定义布局。
2. 解耦数据与设计
JLayouts的一大酷炫功能是成为开发者将HTML代码从PHP代码中解耦的另一工具。在理想的世界里,页面中的100%标记都应由设计师/开发者覆盖,而无需触碰Joomla!核心。这意味着,如果你加载了一个JS文件,你应该在设计师决定不使用你的JS而用另一个库替换它的地方加载。这实际上是我们Joomla!中最重要的一个问题之一,也是为什么大多数设计师在尝试合作一段时间后会感到害怕的原因。
3. 与2.5.x的简单集成
布局系统只包含四个文件。你可以将它们包含在你的库中,以支持2.5版本,或者在你的类中扩展它们。
以前的JLayout系统
使用以前的JLayout系统,一个这样的调用
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
将会在以下位置搜索布局
[0] => templates/mytemplate/html/layouts [1] => layouts
太棒了!这意味着我可以覆盖它。但你也可以通过以下方式强制加载布局的文件夹
$layout = new JLayoutFile('joomla.content.tags', JPATH_SITE . '/components/com_mycomponent/layouts'); $layout->render($itemTags);
这将搜索以下位置的布局
[0] => templates/mytemplate/html/layouts [1] => components/com_mycomponent/layouts
很棒,因为它仍然可以覆盖!
新的要求
使用以前的布局系统,我们仍然存在一些问题
- 想要在其组件中使用布局的开发者必须在每个调用中指定布局的路径或创建自己的扩展类。
- 如果设计师想在博客视图中以不同的方式显示标签,而在分类视图中以不同的方式显示,会怎样呢?
- 设计师如何定制他想要渲染的特定组件字段的显示方式?
我在工作中遇到了这些问题,这就是我开始改进系统的原因。其中一些问题使用旧系统有“硬”解决方案,但我想有一个简单自动的系统,它也能适用于复杂解决方案。
新特性
在我最初的提案之后,Joomla!的魔力开始了,人们提出了更多的建议。最终的结果是一个非常酷的系统,比我的最初提案要好得多。这是开源的魅力。
作为新改进的提示,现在的布局调用可以是这样的
$layout = new JLayoutFile('joomla.content.tags', null, array('debug' => true, 'client' => 1, 'component' => 'com_tags'));
1. 组件布局覆盖
其中一个修改是现在系统会自动在加载的组件中搜索布局。
现在,我们之前使用的相同调用
$layout = new JLayoutFile('joomla.content.tags'); $layout->render($itemTags);
会自动在这些文件夹中搜索布局(按优先级排序)
[0] => templates/mytemplate/html/layouts/com_mycomponent [1] => components/com_mycomponent/layouts [2] => templates/mytemplate/html/layouts [3] => layouts
这意味着你可以使用标准布局,在组件级别覆盖它们,并在模板级别覆盖组件覆盖。
在我们的例子中,开发者可以定制组件中标签的显示方式,设计师可以覆盖组件中标签的显示方式。
2. 强制组件
前面的例子会自动检测当调用布局时的组件。但如果我想以com_tags在前端渲染标签的方式渲染我的标签,会怎样呢?这也通过这个示例调用解决了
$layout = new JLayoutFile('joomla.content.tags', null, array('component' => 'com_tags'));
3. 强制客户端
系统现在自动检测的是调用的客户端。这意味着如果你在前端,它会在前端搜索布局。
但我希望以com_tags在前端渲染标签的方式在后端渲染我的标签!这也通过这个示例调用解决了
$layout = new JLayoutFile('joomla.content.tags', null, array('client' => 1, 'component' => 'com_tags'));
客户端参数支持以下值
- 0,'site' > 前端
- 1,'admin' > 后端
4. 添加包含路径
假设你最终有一个自定义布局文件夹,但你不想存储所有内容。你只想添加一个文件夹,例如,Joomla需要在那里搜索布局,如果没有找到它们,则加载标准布局。例如,在我公司,我们有一个库,包含我们所有组件共享的自定义布局。
这可以通过新的调用完成
$layout = new JLayoutFile('joomla.content.tags'); $layout->addIncludePaths(JPATH_LIBRARIES . '/hacknsa');
这将把/libraries/hacknsa添加到顶级搜索布局(最高优先级)。此方法也支持路径数组。在数组中,请记住,最后一个将具有最高优先级。
5. 后缀
另一个提案(在这种情况下来自Robert Deutz)是能够指定布局的后缀。原始想法是允许扩展加载特定于活动的Joomla!版本或使用默认版本。示例
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25'))); echo $layout->render($this->item->tags->itemTags);
但这只是其中一种用途。想象一下,你需要为RTL(从右到左)语言使用不同的布局。你可以将其添加到所有搜索中,以便在启用活动RTL语言时始终查找。或者想象一个客户的地址,其邮编根据国家/地区在不同的位置/格式中显示。你可以添加对客户国家特定布局的检查。
6. 子布局
我在JLayouts中发现的一个令人不快的事情是,你不能继承布局的设置,并使用它们来渲染代码的另一小部分,而无需再次指定所有选项。让我们看另一个例子:我们在redCOMPONENT中需要的一个使用案例是可定制的发票。我很快想到了布局。这样,我可以有一个全局调用,比如
JLayoutHelper::render('invoice', $invoiceData);
然后在这个布局中,像这样
<div class="invoice">
<div class="customer">
<?php echo $this->sublayout('shopper', $displayData['shopper']); ?>
</div>
<div class="header">
<?php echo $this->sublayout('header', $displayData); ?>
</div>
<div class="products">
<?php echo $this->sublayout('products', $displayData['products']); ?>
</div>
<div class="footer">
<?php echo $this->sublayout('footer', $displayData); ?>
</div>
</div>
这是一个主发票布局调用子布局。所以用户只需覆盖发票的标题,而无需处理系统的其余部分。
当调用子布局时,系统会尝试找到一个与该布局名称相同的文件夹,其中包含子布局。在这个例子中,我们会有一个主要布局invoice.php,在同一文件夹中有一个名为invoice的文件夹,其中包含子布局(shopper.php、header.php、products.php & footer.php)。
子布局将继承传递给父布局的任何设置。因此,它们在相同的包含路径、相同的客户端、相同的组件和相同的后缀中搜索。
7. 调试模式
当你开始处理各种包含路径、客户端、组件等的布局时,你很容易不知道系统从哪里加载布局。这就是为什么我包括了UBU(有用但丑陋:D)调试系统。要启用它,你只需将选项debug传递为true,如下所示
$layout = new JLayoutFile('joomla.content.tags', null, array('suffixes' => array('j3x', 'j25'), 'debug' => true)); echo $layout->render($this->item->tags->itemTags);
你将看到类似
在哪里不使用布局?
当正确使用时,布局很酷,但当在不正确的地方使用时,它就很糟糕。现在每个人都想将一切转换为布局。这就是为什么你可以很容易地找到由文章、横幅、联系人、客户、网站链接、新闻源使用的布局。你会说“但这很酷,不是吗?我们正在节省代码!”不!我们只是在创建一个包含大量if语句的单个布局来处理组件之间的所有差异。
在我看来,使用布局来渲染四个字段没有任何好处。这是必须在模板中完成的事情,并且永远不会在核心之外重用。这就是我的建议:如果它可以在核心之外重用,那么它作为布局是有意义的。布局的示例:渲染列表、按钮、菜单、字段、分页……另一个好的建议:如果它不能被覆盖,那么在布局中更好。
但不是的,布局不是解决所有问题的答案。
其他用途
想象一下当前核心中的jQuery加载。这是从JHtml类中完成的。为什么不让JHtml在组件文件夹中自动搜索覆盖?这样我就可以有我自己定制的jQuery版本,与我的组件中的其他库一起测试。是的,它可能与其他模块要求冲突,但那不就是我们已经有的吗?至少我们将避免多次加载jQuery。这不是布局的任务,而是将相同的概念应用到JHtml上。
现在想象一下,顶级菜单中的一个按钮或布局中的某些内容存在一个错误。你可以在自己的组件中的布局覆盖中修复它,并等待核心修复它。同样,如果你有一个与核心冲突的库。节省了很多支持,解释问题是一个核心错误。
这些都是该概念背后的某些想法。
结论
布局是一个非常强大的工具,它可以帮助我们改善程序员与设计师之间的关系。布局可以用在很多地方。其中一些还未被发现,一些正在等待有人来完成这项工作。 你想帮助我们吗?
在 Joomla 社区杂志上发表的一些文章代表了作者对特定主题的个人观点或经验,可能与 Joomla 项目的官方立场不完全一致
通过接受,您将访问 https://magazine.joomla.net.cn/ 外部的第三方服务
评论