JLayout 为 Joomla! 3.2 提升功能
本文介绍了 Joomla! 3.2 中新 JLayouts 功能。大多数更改都集中在提高第三方开发者的系统灵活性。
一些历史背景
让我们用一个例子来说明:你有一些带有标签的文章,但联系人也有标签,分类也有标签...
在 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/之外的第三方外部服务
评论