开发者指南

编写文档

非常欢迎您对October文档的作出贡献。 如果您想贡献,请遵循以下规则。 如何设计完美的October文档页面:

  1. 每个至少有一个H2标头的页面应该有一个TOC列表。 TOC列表应该是H1标头之后的第一个元素。 TOC应该链接到页面上的所有H2标头。
  2. 即使有引言部分,TOC下面也应该有介绍性文本。如果不是真的需要,你可能想要摆脱介绍部分。不要单独留下TOC。
  3. 尝试仅使用H2和H3标头。
  4. 每个H2和H3标题应该有一个定义为“ ”的链接
  5. 仅对TOC列表使用UL标签。
  6. 避免短,1句,段落。合并短段落并尝试更加冗长。
  7. 避免在代码部分下方悬挂段落。将这些段落与代码块上方的文本合并。
  8. 对代码相关的所有内容使用内联code标签 - 变量名,函数名,语法示例等。
  9. strong标签用于其他所有内容。
  10. 不要犹豫与其他文档文章交叉链接。不需要在同一段落中添加指向同一篇文章的链接。
  11. 参见cms-pages.mdcms-themes.md文件供您参考。

PSR标准的例外情况

October使用的PSR标准有一些例外。

控制器方法可以有一个下划线

PSR-2声明方法必须在camelCase中。 但是,在Backend控制器中,October将为AJAX处理程序添加操作名称,以定义受控上下文。 例如:

  1. public function index()
  2. {
  3. // This is the index page (index action)
  4. }
  5. public function index_onDoSomething()
  6. {
  7. // AJAX handler only works on the index action
  8. }
  9. public function onDoSomethingElse()
  10. {
  11. // AJAX handler works globally for all actions
  12. }

必须为这些方案授予例外。

后续表达式在新一行

PSR-2没有明确声明后续表达式应与右括号位于同一行。

以下代码被认为是有效的,建议更好的逻辑间隔:

  1. if ($expr1) {
  2. // if body
  3. }
  4. elseif ($expr2) {
  5. // elseif body
  6. }
  7. else {
  8. // else body;
  9. }
  10. try {
  11. // try body
  12. }
  13. catch (FirstExceptionType $e) {
  14. // catch body
  15. }
  16. catch (OtherExceptionType $e) {
  17. // catch body
  18. }

基于技术性,这是可接受的偏好,在这种情况下,当使用SHOULD,MUST等时,PSR-1和PSR-2不明确。 但是,在撰写本文时,PSR-2 codesniffer规则表明它无效,因此可能需要例外。

开发人员标准和模式

本节介绍了我们强烈建议每个人遵循的一些标准,特别是如果您要在Marketplace上发布您的产品。

Vendor命名

命名空间中的vendor或作者代码必须以大写字符开头,不应包含下划线或短划线。 这些是有效名称的示例:

  1. Acme.Blog
  2. RainLab.User
  3. Happygilmore.Golf

这些是不是有效的名称示例:

  1. acme.blog
  2. rainLab.user
  3. Happy_gilmore.Golf

仓库命名

将工作发布到版本管理库(例如Git)时,请使用以下命名作为约定。 插件应该用-plugin后缀和可选的oc -前缀命名。

  1. blog-plugin
  2. oc-blog-plugin

主题应该用-theme后缀和可选的oc -前缀命名。

  1. happy-theme
  2. oc-happy-theme

PHP变量命名

使用 camelCase 除以下情况外:

1.数据库属性和关系应该使用snake_case 1.返回参数和HTML元素应该使用snake_case 1.语言键应使用snake_case

HTML元素命名

Form元素名称应该使用snake_case(下划线)

  1. <input name="first_name">

如果名称是数组,则数组键可以是StudlyCase或snake_case。

  1. <input name="ForumMember[first_name]">
  2. <input name="forum_member[first_name]">

元素ID应为驼峰式或连字符(短划线)

  1. <div id="firstNameGroup">
  2. <input id="firstName">
  3. </div>
  4. <div id="first-name-group">
  5. <input id="first-name">
  6. </div>

元素类名称应使用连字符(破折号)

  1. <div class="form-group">
  2. <input class="form-control">
  3. </div>

视图文件命名

Partial视图应以下划线字符开头。 而Controller和Layout视图不以下划线字符开头。 由于视图通常位于单个文件夹中,因此下划线(_)和短划线( - )字符可用于组织文件。 短划线用作空格字符的替代。 下划线用作斜杠字符(文件夹或命名空间)的替代。

  1. index_fancy-layout.htm <== Index\Fancy layout
  2. form-with-sidebar.htm <== Form with sidebar
  3. _field-container.htm <== Field container (partial)
  4. _field_baloon-selector.htm <== Field\Baloon Selector (partial)

视图文件必须以.htm文件扩展名结尾。

类文件命名

类通常放在classes目录中。 我们建议后缀和前缀。

  1. Manager
  2. Builder
  3. Writer
  4. Reader
  5. Handler
  6. Container
  7. Protocol
  8. Target
  9. Converter
  10. Controller
  11. View
  12. Factory
  13. Entity
  14. Engine
  15. Bag

不要对命名感到不拿耐烦。 是的,名字非常重要,但它们不足以浪费大量时间。 如果你不能在五分钟内想出一个好名字,继续前进。

事件命名

指定事件名称时。 after不在事件中使用,只使用before。 例如:

  1. beforeSetAttribute - 这个事件来before任何默认逻辑。
  2. setAttribute - 此事件来自after任何默认逻辑。

可能的事件应涵盖全局和本地版本。 全局事件应以模块或插件名称为前缀。 例如:

  1. // For global events, it is prefixed with the module or plugin code
  2. Event::fire('cms.page.end');
  3. // For local events, the prefix is not required
  4. $this->fireEvent('page.end');

避免在事件名称中使用诸如onSomething之类的术语,可以使用单词bind/fire表示此动作词。

最好将调用对象作为第一个参数传递给全局事件,本地事件不应该需要这个。 当暂停时,本地事件优先于全局事件,或者在处理时优先于本地事件。

  1. // Local event
  2. if ($this->fireEvent('beforeAddContent', [$message, $view], true) === false)
  3. return;
  4. // Global event
  5. if (Event::fire('mailer.beforeAddContent', [$this, $message, $view], true) === false)
  6. return;

当期望多个结果时,很容易组合这样的数组:

  1. // Combine local and global event results
  2. $eventResults = array_merge(
  3. $this->fireEvent('form.beforeRefresh', [$saveData]),
  4. Event::fire('backend.form.beforeRefresh', [$this, $saveData])
  5. );

数据库表命名

表名应以作者和插件名称为前缀。

  1. acme_blog_xxx

布尔列名称应以“is_”为前缀

  1. is_activated
  2. is_visible

这是因为模型属性可能会发生冲突,例如,Model类中的public $visible;与具有相同名称的数据库列冲突。 某些列名称是例外,例如notify_user

如果您的插件扩展了属于其他插件的表,则添加的列名应该以作者和插件名为前缀:

  1. acme_blog_category_id

作者和插件名称的首字母缩写也是可以接受的:

  1. ab_category_id

组件命名

组件类通常位于components目录中。 组件的名称应代表其主要功能。

要显示记录列表,请使用List后缀,例如:

  1. ProductList
  2. ProductReviewList
  3. CategoryList

要显示单个记录,请使用Details后缀,例如:

  1. ProductDetails
  2. CategoryDetails

使用后缀有助于避免与控制器和模型名称冲突。 或者,对于名称具有描述性且不冲突的情况,您可以为没有后缀的组件命名:

  1. ProductReviews
  2. CustomerCheckout
  3. SeoDirectory
  4. UserProfile

控制器命名

控制器通常放在controllers目录中,用于后端控制器。 控制器的名称应为复数,例如:

  1. People
  2. Products
  3. Categories
  4. ProductCategories

模型命名

模型通常放在models目录中。 模型的名称应该是单数,例如:

  1. Person
  2. Product
  3. Category
  4. ProductCategory

在扩展其他模型时,您应该在字段前面添加至少插件名称。

  1. User::extend(function($model) {
  2. $model->hasOne['forum_member'] = ['RainLab\Forum\Models\Member'];
  3. });

完全限定的插件名称也是可以接受的,例如:

  1. $user->rainlab_forum_member

模型范围

如果模型范围返回用于链接的查询对象,则应使用“apply”作为前缀,以指示它们正在应用于查询。 定义为:

  1. public function scopeApplyUser($query, $user)
  2. {
  3. return $query->where('user_id', $user->id);
  4. }

然后应用于模型:

  1. $model->applyUser($user);

虽然apply是理想的前缀名称,但以下是我们为链接范围推荐的一些其他前缀:

  1. - is
  2. - for
  3. - with
  4. - without
  5. - filter

如果范围返回除查询之外的任何内容,则可以使用任何名称。 非链式范围的一些可接受的名称:

  1. - find
  2. - get
  3. - list
  4. - lists

Class引导

这些要点应以轻松的方式考虑:

  1. 在类中,属性和方法应声明为protected,以支持private。 所以所有类都可以用作基类。
  2. 如果属性包含单个值(不是数组),则使属性“public”而不是get/set方法。
  3. 如果属性包含集合(是一个数组),则使用getgetPropertiesgetPropertysetProperty创建属性protected

环境配置

使用MySQL的严格模式

当启用MySQLSTRICT_TRANS_TABLES模式 时,服务器将执行严格的数据类型验证。 强烈建议在开发期间在MySQL中启用此模式。 这允许您在代码使用enabled strict模式到达客户端服务器之前查找错误。 可以在my.cnf(Unix)或my.ini(Windows)文件中启用该模式:

  1. sql_mode=STRICT_TRANS_TABLES