该包已被 废弃 并不再维护。没有建议的替代包。

维护者

详细信息

github.com/cargomedia/CM

源代码

问题

安装数: 20,839

依赖: 1

建议者: 0

安全: 0

星星: 10

关注者: 9

分支: 18

1.258.5 2017-08-03 09:46 UTC

This package is not auto-updated.

Last update: 2019-02-20 17:48:34 UTC


README

该项目不再维护。如果您想接管,请联系我们 tech@cargomedia.ch

CM 框架 构建状态

主要概念

命名空间

命名空间将相关代码分组。命名空间用作类名的前缀。CM 是一个命名空间,类名可以是 CM_Foo_BarZoo

站点

一个应用程序可以服务多个 站点(扩展 CM_Site_Abstract)。

在处理之前,每个 HTTP 请求(CM_Http_Request_Abstract)都会与可用的站点(::match())进行匹配。

一个站点包含多个 命名空间(用于模型和控制台)和 主题(用于视图)。

视图

视图(扩展 CM_View_Abstract)可以被渲染,通常是作为 HTML。以下视图类型是预先定义的

  • CM_Layout_Abstract:HTML 文档。
  • CM_Page_Abstract:Web 应用程序的一页。实际上是一个组件本身。
  • CM_Component_Abstract:HTML 文档的子部分。
  • CM_Form_Abstract:带有输入元素和操作的表单。
  • CM_FormField_Abstract:表单输入字段。
  • CM_Mail_Mailable:电子邮件。

模型

模型(扩展 CM_Model_Abstract)代表一个“现实世界”的对象,从键值存储中读取和写入数据,并在其上提供功能。

每个模型都有一个 id,它可以用来实例化

$foo = new Foo(123);

默认情况下,构造函数期望一个整数值作为 ID。内部,它被存储为一个键值存储(数组),如果需要更复杂的模型标识,则可以公开。

模式

为了验证和强制执行模型字段的类型转换,定义一个合适的模式定义

	protected function _getSchema() {
		return new CM_Model_Schema_Definition(array(
			'fieldA' => array('type' => 'int'),
			'fieldB' => array('type' => 'string', 'optional' => true),
			'fieldC' => array('type' => 'CM_Model_Example'),
		));
	}

具有模型类名作为类型的字段将在读取和写入数据存储时在 对象其 ID 的 JSON 表示 之间进行转换。

持久化数据

如果存在,将使用 持久化 存储适配器来加载数据和保存模型数据。

	public static function getPersistenceClass() {
		return 'CM_Model_StorageAdapter_Database';
	}

在这个例子中,当实例化现有模型或更新模式字段时,将调用数据库适配器的 load()save() 方法。

CM_Model_StorageAdapter_Database 将使用以下命名约定将模型持久化到数据库中

  • 表名:模型的类名的小写
  • 列名:模式字段的名称

您可以使用 _get()_set() 访问模型字段,这些方法将考虑模式进行类型强制转换。建议为每个字段实现一对获取器和设置器,以保持字段名内部化

 	/**
 	 * @return string|null
 	 */
 	public function getFieldB() {
 		return $this->_get('fieldB');
 	}

 	/**
 	 * @param string|null $fieldB
 	 */
 	public function setFieldB($fieldB) {
 		$this->_set('fieldB', $fieldB);
 	}

 	/**
 	 * @return CM_Model_Example
 	 */
 	public function getFieldC() {
 		return $this->_get('fieldC');
 	}

 	/**
 	 * @param CM_Model_Example $fieldC
 	 */
 	public function setFieldC($fieldC) {
 		$this->_set('fieldC', $fieldC);
 	}

默认情况下,数据在Memcache中在多次读取之间进行缓存。使用getCacheClass()来改变此行为

	public static function getCacheClass() {
		return 'CM_Model_StorageAdapter_CacheLocal';
	}

或者,如果您不使用持久化存储适配器,您可以实现一个自定义方法_loadData(),该方法应返回一个包含模型键值数据的数组。在这种情况下,您的设置器负责持久化,并且仍然应该调用_set()进行缓存。

创建和删除

具有持久化存储适配器的模型可以通过使用其设置器后跟commit()来创建。

	$foo = new Foo();
	$foo->setFieldA(23);
	$foo->setFieldB('bar');
	$foo->commit();

对于删除模型,只需调用

	$foo = new Foo(123);
	$foo->delete();

或者,如果您不使用持久化存储适配器,您可以在_createStatic(array $data)中实现自己的创建逻辑,然后使用以下方式创建模型:

	$foo = Foo::createStatic(array('fieldA' => 1, 'fieldB' => 'hello world'));

在这种情况下,请确保在_onDelete()中删除相应的记录(见下文)。

事件处理

以下方法将在模型生命周期的不同事件中被调用

  • _onCreate():在持久化后,当模型被创建时。
  • _onChange():在持久化后,当字段的值被更改时。模型创建后也会调用。
  • _onDelete():在持久化之前,当模型被删除时。

分页

分页是有分页功能的有序集合。

分页的数据源是分页源(CM_PagingSource_SqlCM_PagingSource_Elasticsearch等)。可以通过enableCache()启用缓存。

分页中的项目在被返回之前可以进行处理。例如,可以实例化一个对象,该对象是从数据库返回的id。

命名约定

CM_Paging_<Type of item>_<Lookup description>
CM_Paging_Photo_User                           # All photos of a given user
CM_Paging_User_Country                         # All users from a given country

文件结构

类定义应按主题分组,并存储在公共目录中。在这样一个主题模块中,应使用目录来分组具有共同父类的文件。一个主题模块可以再次包含另一个(子)主题模块的目录。

主题模块“付款”的示例,位于另一个主题模块“会计”内部

library/
└── CM
    └── Payments
        ├── Accounting
        │   ├── Account.php
        │   ├── Transaction.php
        │   └── TransactionList
        │       ├── Abstract.php
        │       └── User.php
        ├── Bank.php
        ├── BankList
        │   ├── Abstract.php
        │   ├── All.php
        │   └── PaymentProvider.php
        ├── ExchangeRateUpdater.php
        └── SetupScript.php

组件页面之类的视图需要位于其相应的目录中。建议在子目录中按主题对它们进行分组。

主题“付款”的组件示例

library/
└── CM
    └── Component
        └── Payments
            ├── AccountList.js
            ├── AccountList.php
            ├── TransactionList.js
            └── TransactionList.php

创建新项目

克隆CM骨架应用程序

在您的工作区中运行

composer create-project cargomedia/cm-project --stability=dev <project-name>

这将创建一个新的目录<project-name>,其中包含基于CM的项目。

命名空间创建、站点设置

CM框架提供了一个基础,应该被扩展。我们自己的库应包含在不同的命名空间中。要创建一个,只需运行

bin/cm generator create-namespace <namespace>

添加新模块

为了简化创建常见的框架模块,同时也有助于理解其结构,有一个生成器工具。它有助于构建框架视图和简单的类。它还允许轻松添加新的命名空间或站点。

generator create-view <class-name>

基于提供的创建新的视图。它将创建php类、javascript类、空html模板和less文件。它还会寻找最合适的抽象类来扩展。

generator create-class <class-name>

创建新的类。

命令行工具

CM 框架自带一组命令行工具,可以轻松运行常见的 PHP 程序。要查看所有可用的命令,只需执行 bin/cm

Usage:
 [options] <command> [arguments]

Options:
 --quiet
 --quiet-warnings
 --non-interactive
 --forks=<value>

Commands:
 app fill-caches
 app generate-config-internal
 app set-config <filename> <config-json> [--merge]
 app setup [--reload]
 cache clear
 console interactive
 db db-to-file <namespace>
 db file-to-db
 frontend generate-favicon
 frontend icon-refresh
 generator create-class <class-name>
 generator create-module <module-name> [--single-module-structure] [--module-path=<value>]
 generator create-view <class-name>
 job-distribution start-worker
 location outdated [--verbose]
 location upgrade [--without-ip-blocks] [--verbose]
 maintenance start
 media-streams import-archive <stream-channel-media-id> <archive-source>
 media-streams import-video-thumbnail <stream-channel-media-id> <thumbnail-source> <create-stamp>
 message-stream start-synchronization
 migration add [--namespace=<value>] [--name=<value>]
 migration run [--name=<value>]
 search-index create [--index-name=<value>] [--skip-if-exist]
 search-index delete [--index-name=<value>]
 search-index optimize
 search-index update [--index-name=<value>]

部署

除了设置整个基础设施(http 服务器,各种服务)之外,应用程序本身也需要做一些准备。

类类型

每个 CM 应用程序都严重依赖于类型,这些类型是类的一个整数标识符。为了保持固定的标识符(类名可以更改),我们需要将这些存储在版本控制系统中存储的配置文件(internal.php)中。要生成类型,运行

$ bin/cm app generate-config-internal

这将生成应用程序运行所需的 resources/config/internal.phpresources/config/js/internal.js 文件。请将此文件保留在版本控制系统中,因为它需要在版本之间保留。

配置脚本

大多数 CM 应用程序都需要设置服务并/或插入一些初始数据。为此,CM 框架使用所谓的配置脚本。有一个内置命令可以运行配置属性 $config->CM_App->setupScriptClasses 中定义的所有设置脚本。

$ bin/cm app setup

配置脚本负责设置与应用程序相关的一切,从创建数据库模式到加载固定数据。

配置脚本

所有这些脚本都需要是扩展 CM_Provision_Script_Abstract 的类,并实现 loadshouldBeLoaded 方法。任何时间脚本即将被加载时,它们将首先通过运行 shouldBeLoaded 来检查它们是否确实应该被加载。一旦这是肯定的,它将运行 load

此外,配置脚本可以实现 CM_Provision_Script_UnloadableInterface,并实现相应的 unloadshouldBeUnloaded 方法。

迁移脚本

迁移脚本位于 [modulePath]/resources/migration 目录中,它们按照模块注册顺序执行(见 composer.json 中的 extra.cm-modules),然后按脚本文件名自然顺序。

  • 脚本类将在运行时 require 并实例化
  • 脚本类名必须是唯一的
    • 按照惯例,在类名中添加一个时间戳以避免冲突
  • 脚本类必须实现 CM_Migration_UpgradableInterface 接口
  • 脚本可以可选地实现 CM_Service_ManagerAwareInterface 以获取对服务管理器的访问权限
  • 如果可用,将在脚本执行期间显示 UpgradableInterface::up PHP 文档块

执行迁移脚本

  • cm 迁移运行
    运行所有尚未成功执行的脚本
  • cm 迁移运行 --name=<filename>
    (重新)运行特定的脚本,通过其文件名(不带扩展名)

例如

bin/cm migration run
- 1485180420_Foo…
- 1485180453_Bar: some description coming from PHP doc…

生成迁移脚本

  • cm 迁移添加
    生成迁移脚本,默认在 [root]/resources/migration 中,并使用当前的 git 分支名称
  • cm 迁移添加 --namespace=<module-name> --name=<script-name>
    在特定模块/具有特定名称中生成迁移脚本

例如

bin/cm migration add --namespace=Foo --name=Bar
`/home/vagrant/cm/library/Foo/resources/migration/1485180453_Bar.php` generated