使您的Magento代码更便携

使您的Magento代码更便携

2015年7月28日发布 in 发展历程
Agile Software 发展历程 at 优雅的骆马
Agile Software 发展历程 at 优雅的骆马
2015年2月17日
移植到Magento 2插件博客封面
使用插件将Magento 1模块移植到Magento 2
2015年8月13日

我们都知道我们应该编写可移植的代码。可重用的功能肯定会带来效率的提高,而且可移植的代码自然也更清晰,组织更好并且易于维护。

在Magento网站的代理或内部开发中,“完整构建”周期使它很容易陷入将功能和表示形式视为一个实体的模式。功能代码贯穿整个特定主题,随着时间的流逝,功能无关的临时模块变得笨拙,并且应用程序过度依赖于有关站点特定用例的假设。可以肯定的是,当一项特别出色的功能与将来的另一个站点相关时,要查找使该功能发生变化的所有组件都是一件繁琐的事情。

 

出现这种情况的原因是“急于完成”的思维定势,但保持代码更独立,可重用和可维护并不一定意味着要花费大量时间。练习以下技巧后,只需花费很少的精力,便可以发挥很大的作用。它们也几乎没有启示性。实际上,您可能一直在第三方扩展中看到它们–也称为强制性可移植性的方案。所需的最重要的努力只是一些预见。

“一体式”方法

作为一个经常会混淆主题和功能的熟悉模式的快速示例,让我们设想一个假想的网站构建。纳入指定主题的注意事项有两个功能:支持在产品详细信息页面上的媒体库中显示YouTube或Wistia嵌入式视频(使用缩略图之类的信息,直接从视频服务中提取),以及自定义徽标。产品列表页。

当我们一起处理主题和这些功能时,我们的代码库开始增长,最终的结果往往看起来像这样:

我想像过,我们视频和产品徽章所需的各种块,辅助方法和观察者方法都集中在一个模块(MyCompany_MyStore)中。当我们充实该站点时,在这里和那里添加一种方法将是自然的结果。同样自然的是,对主题结构本身的添加最终导致对关键模板的直接覆盖,毫无疑问,该模板与主题中的许多其他模板并排放置。所有必要的布局更改都会在主题的local.xml文件中进行,当然,尽管未显示,但所有必要的样式都已合并到主题的主要styles.css中。

这两个功能可能都依赖于产品属性。对于视频,这可能是保存一个或多个嵌入代码的文本属性。对于徽章,带有预定义徽章文本的多选属性。因此,如果需要额外的工作,我们假设我们通过简单的管理界面创建了这些属性。

查看上面的文件列表,当然没有关于视频功能的关键逻辑所在位置的线索。如果我们想找出原因,就必须开始寻找代码本身。

为了获得更清晰,更便携的结构,我们需要回到开发开始之前,并问一个重要的问题:什么仅构成我们主题的一部分,什么构成功能?

古老的格言:关注点分离

这个问题看似很明显,但是每次坐下来确定一个开发领域时,都需要进行练习,使其成为您的思维方式的一部分。如果我们问假想网站设计的哪些部分仅是“主题”组件,我们将很快确定出我们注意到的两个功能–视频和产品徽章– 做 n’t fit the bill.

从一开始就以这种思维方式,而不是将我们的工程代码放在一起,而是为这些功能专门创建了两个单独的模块:MyCompany_Videos和MyCompany_Badges。前者可能包含用于从YouTube或Wistia提取信息的模型,而产品保存者可以在适当的时候这样做,而后者可能具有一些辅助方法来将产品属性干净地处理为适当的输出。两者当然都包含块。

通过简单的第一步,我们实际上已经为我们的代码组织创造了奇迹。即使我们走得更远,我们也至少有一个起点,可以一目了然地跟踪我们的功能代码。

需要注意的是,对于每个功能,您当然可以采用单独模块的这种方法。我们不想最终得到30个模块,每个模块都包含一个辅助方法!将少量功能分组到一个包罗万象的模块中就可以了。 (实际上,示例中的简单功能以它们的当前形式沿这条线行驶,但是我们假设它们在现实世界中的影响范围会更大。)这种判断调用变得越来越容易越直观,您问的功能和外观分离的问题就越多。

主题注意事项

在我们的主题文件中,橡胶在分离特征时遇到了麻烦,与第一步相比,这里有更多的挑战。

简单分隔

首先,我建议不要将真正针对功能的代码放在特定于站点的主题中。如果可能的话,应将其放在后备方案中的通用位置:基本/默认值,或者rwd /默认值(如果文件扩展或依赖Magento的响应主题)。如果我们要在产品详细信息页面上构建嵌入式视频之类的功能,那为什么要依赖于任何特定主题?通过将文件定位在更全球化的位置,我们确保可以在添加到Magento安装的任何商店中使用我们的功能,而无需从主题到主题之间挑选和复制组件。更偷偷摸摸的是,这使我们开始提出其他问题。没有特定主题可工作的地方 我们的变化去了吗?

最简单的答案是针对布局文件。我们已经为不同的功能定义了不同的模块;这些模块也可以定义自己的布局文件。因此,现在有了video.xml和badges.xml,而不是与功能相关的布局添加项与local.xml中的常规主题更改共享空间。

范本

对于模板文件,事情变得更加棘手。我们应该首先将逻辑尽可能地移到单独的全新模板中。核心主题提供了大量文本列表块(在布局中定义为“ core / text_list”类型),将有助于此工作;这些块类型的子代将自动输出。不过,就我们而言,几乎可以肯定我们必须覆盖两个核心模板的标记:产品列表模板(用于输出徽章)和媒体模板(用于输出视频)。

一种策略是使用布局XML更改右侧块的模板路径。 ( <动作方法=“ setTemplate”><path>file.phtml</path></action>) This is a fine solution for smaller, little-touched 模板s. It’s problematic for many others, though. If we change the 路径 of the 产品 清单 模板, we’ve certainly accomplished the goal of making it clear where our feature 码 resides, but at the cost of maintainability of the theme. If another developer 在herits our 码 and goes looking for the right place to tweak the 产品 清单 模板, he or she might be 在 for some frustration.

值得注意的是,如果我们要扩展Magento的自适应主题,则会添加许多文本框,以帮助解决我们的问题。例如,我们可能发现特定于响应的“ 产品_list.name.after”块可能恰好适合放置我们的产品徽章而无需触摸产品列表模板。实际上,我们可以将其与JavaScript中的某些DOM操作配对使用,以将内容准确地移动到我们想要的位置–例如,在产品名称之前而不是之后。 (不要为这最后一种技术而发疯。在我刚才提到的示例中,这仅仅是因为内容已被放置 几乎 确切地讲,页面的语义或代码的可维护性不会受到太大影响。)

如果其他所有方法均失败,请继续使用主题中的模板替代来包含适当的功能逻辑。或者尝试这种方法以获取大小:在主题中需要的位置添加一些文本列表块,然后使用它们通过模块特定的模板文件添加内容。是的,此策略仍取决于特定主题,以便功能起作用。但是占用空间尽可能小(且通用),而主要事件仍包含在特定于功能的主题文件中。

附属资产

对于JavaScript和CSS,将与功能相关的代码与主题分开非常简单。唯一棘手的问题是,特定功能的大小是否确实足以保证单独的JS或CSS文件,因为除非您为这些类型的文件启用文件合并,否则它们将增加页面加载所需的HTTP请求数量。

不过,值得注意的是,Magento的响应主题及其通过Sass / Compass进行CSS编译的采用使代码的组织变得更加容易,而无需单独的最终CSS文件。在这个新范例中,styles.css是从按关注程度分组的几个“部分”文件的内容中编译而成的。由于这种结构,与特定功能相关的样式保持清晰分离就像添加一个新的部分样式(例如skin / 前端 / 我的商店 / 默认 / 脚本 / 模组 / _徽章.scss)并将其导入styles.scss一样简单。在中了解有关使Sass成为工具集一部分的更多信息 Magento的知识库.

最后一点,针对某个功能的真正独立的CSS文件确实具有能够驻留在如上所述的后备主题中的优点,因此无需依赖特定主题。显然,这与结构CSS相比,与装饰CSS更为相关,并且再次归结为对功能复杂性的判断。

保留在代码中

我们的示例功能依赖于几个不同的产品属性,我想指出的是,可以轻松地将其添加到管理员中。管理员属性管理是商家添加到目录的强大工具 内容 无需触摸代码。创建用于分层导航,产品比较或产品详细信息页面上的规格列表的属性是此界面的重要用途。

但是,当某项站点功能依赖于特定属性时(例如,在我们的视频嵌入代码和徽章文本属性的情况下),诉诸于管理人员输入的内容是一个糟糕的解决方案。如果将要素从登台环境迁移到生产环境时,缺少某个特定属性怎么办?如果两者之间的定义不一致,该怎么办?我们的功能代码的清晰度和可重用性也受到严重影响,因为只能通过找到它们的使用位置来识别必要的属性。 (即使那样,也只能猜测其确切定义。)

这种属性属于代码的其余部分,而正确的位置位于模块安装/升级脚本中。您可以在Magento核心代码中找到大量示例。升级脚本位于模块的sql目录中,并且要使其工作目录名称与之匹配的安装资源必须在etc / config.xml中的“ global / resources / * / setup”之类的节点中进行定义。 Mage_Catalog_Model_Resource_Setup类对于创建产品属性是必需的,该属性在升级脚本中使用addAttribute方法完成。

如果您不熟悉此技术,可能会令您感到恐惧,但这是编写可靠且可维护的功能代码的关键一步。稍加练习,再仔细研究一下核心代码库对addAttribute的使用,它将很快成为旧帽子。 (检查Mage_Catalog_Model_Resource_Setup及其祖先Mage_Eav_Model_Entity_Setup的_prepareValues方法,以获取可在任何产品属性上设置的配置值的即时摘要。)

相同的原理可以应用于您的功能希望包含的任何内容,包括CMS静态块或自定义变量。 (并且不敢对产品或类别ID进行硬编码。创建“系统配置”值来捕获此类信息。有关“系统配置”的更多信息,请参见下文。)可以在升级脚本中创建任何类型的内容,并且如果代码依赖于此内容,代码就是它所属的地方。

注意:如果要创建功能依赖的CMS内容,则适当类型的升级脚本实际上是数据升级脚本,该脚本在config.xml中共享相同的安装资源定义,但位于数据目录中而不是sql中。主要区别在于,Magento应用程序在运行数据升级脚本时已完全启动,因此您可以使用标准模型逻辑来创建和保存内容。

你能关掉它吗?

对于最后一部分,请考虑以下问题:如果我们需要删除网站功能怎么办?是否可以轻松完成,还是尝试删除几行代码会导致寻找所有小的引用和依赖关系,而这些引用和依赖关系现在使所有事情都崩溃了?

我想这个问题的答案本身就可以证明代码是多么易于移植。无论如何,为什么不完全不接触代码就可以启用/禁用我们网站上的功能?我们在使功能代码尽可能独立的方面已走了很远;为什么不加倍努力并添加一个开/关开关?这样做非常简单。

您毫无疑问会熟悉Magento管理员的“系统配置”区域,其中包含许多站点设置。我们的视频和产品标志模块需要的是此管理部分中的几个是/否值,以控制是否启用这些功能。如果您不熟悉创建这样的价值观,那么就不用担心了。任何模块的etc / system.xml中的简单XML结构都可以定义它们,而在核心代码库中打开几个这样的文件将迅速使过程神秘化。如果要创建自己的“系统配置”部分而不是添加到现有的“系统配置”部分,则需要付出更多的努力,因为这些部分具有特定的管理员用户权限。但这甚至只需要检查另一种类型的模块配置文件– etc/adminhtml.xml – to get a handle 上.

定义这些值后,只需在模块的相应入口点调用Mage :: getStoreConfig即可检查是否启用了功能。 (任何对布局XML中的块方法的调用,例如setTemplate,也可以使用“ ifconfig”属性使它们的执行取决于这些值。)

可移植代码的隐藏优势

我们假设的代码库的最终快照可能类似于:

在此示例中,我们选择在布局文件中使用setTemplate来更改产品媒体模板的位置,从而说明了“视频”命名空间下的新模板。不过,由于此功能利用了全新的模板,因此我们设法避免了产品徽章覆盖任何模板。当然,我们的新模块包含适当的安装/升级脚本,以设置必需的产品属性,并定义用于启用这些功能的系统配置值。

经过巨大改进的新结构使您可以在何处清楚地找到与某些功能相关的代码,而将这些功能提取到其他地方使用将更加容易。即使我们从来没有机会将代码移植到其他站点,更高的可维护性也肯定会带来好处。

这些是开发级别的收益,但并不是唯一的收益。在整篇文章中,我都反复提到了将主题与功能分开的必要思维方式,这是一个循环的过程。以这种方式考虑您的项目将导致组织更好的代码,并且持续编写更好的代码将重新出现并改善您对需求的思考方式。在敏捷方法学方面,我一开始概述的代码库结构可能来自带有简单“产品列表页面”和“产品详细信息页面”任务的项目积压。从事形式与功能分离的开发人员将很快认识到视频和产品标志功能应得到提升;应该与主题无关地讨论,区分优先级和发展它们。像这样的常规思维,您将更快地交付工作代码,与客户或项目所有者进行更好的对话,并为以自然方式扩展功能提供更好的基础。

发表评论

您的电子邮件地址不会被公开。 必需的地方已做标记 *

该网站使用Akismet减少垃圾邮件。 了解如何处理您的评论数据.

最近的帖子查看全部
2020年10月22日

Covid世界中的假日销售:应对挑战

毫无疑问,2020年是历史性的一年。火灾,全球大流行,暴动,老虎王等’只是冰山一角。如 […]
2020年8月7日

涡轮增压ZZPerformance的付费搜索

2020年7月30日

Intermix Beats M1 End of Life with 优雅的骆马 Accelerator