PageRenderTime 39ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/zh/models/datasources.rst

https://github.com/steinkel/docs
ReStructuredText | 297 lines | 239 code | 58 blank | 0 comment | 0 complexity | 4866b8e4b37f66c5dcc071bd72708e18 MD5 | raw file
  1. 数据源
  2. ######
  3. 数据源是模型和模型所代表的数据来源之间的联系在很多情况下数据是从关系型数据库
  4. 中取得比如 MySQLPostgreSQL 或者 Microsoft SQL ServerCakePHP 的发布就带有若干针对数据库的
  5. 数据源(请参看 ``lib/Cake/Model/Datasource/Database`` 中的类文件)为了便利摘录
  6. 如下
  7. - Mysql
  8. - Postgres
  9. - Sqlite
  10. - Sqlserver
  11. .. note::
  12. 你可以在 `GitHub 上的 CakePHP 数据源代码库 <https://github.com/cakephp/datasources/tree/2.0>`_
  13. 中找到更多社区贡献的数据源
  14. 当在 ``app/Config/database.php`` 中指定数据库连接配置时CakePHP 会以透明地使用
  15. 相应的数据库数据源用于所有的模型操作所以即使你并不知道数据源你也已经一直
  16. 在使用它们了
  17. 所有上述数据源继承于一个基类 ``DboSource``它汇集了大多数关系型数据库通用的一些
  18. 逻辑如果你决定编写一个 RDBMS 数据源你最好从这些中的一个(例如 MySQL 或者
  19. SQLite)开始
  20. 当然大多数人还是感兴趣于为外部数据来源编写数据源比如远程 REST API或者甚至
  21. LDAP 服务器所以这就是我们下面要介绍的
  22. 数据源的基本 API
  23. ================
  24. 数据源能够而且 *应当* 实现至少下面中的一个方法``create````read``
  25. ``update`` / ``delete`` (方法的真正签名和实现细节在这里不重要之后会述及)
  26. 你不必实现上述方法中不必要的部分 如果你需要只读的数据源就没有理由实现
  27. ``create````update`` ``delete``
  28. 对所有 CRUD 方法都要实现的方法
  29. - ``describe($model)``
  30. - ``listSources($data = null)``
  31. - ``calculate($model, $func, $params)``
  32. - 至少下列之一
  33. - ``create(Model $model, $fields = null, $values = null)``
  34. - ``read(Model $model, $queryData = array(), $recursive = null)``
  35. - ``update(Model $model, $fields = null, $values = null, $conditions = null)``
  36. - ``delete(Model $model, $id = null)``
  37. 也有可能(有时还挺有用)在数据源里定义 ``$_schema`` 类属性而不是在模型中
  38. 差不多就这些把这个数据源和一个模型联系起来你就可以象你通常那样使用
  39. ``Model::find()/save()/delete()``而调用这些方法的适当的数据以及/或者参数就会被
  40. 传递给数据源在那里你可以决定要实现任何你需要的特性(例如 Model::find 选项比如
  41. ``'conditions'`` 的解析 ``'limit'`` 或者甚至你自己的定制参数)
  42. 一个例子
  43. ========
  44. 你想要编写自己的数据源的一个常见原因是当你要使用通常的
  45. ``Model::find()/save()/delete()`` 方法来访问第三方 API让我们来编写一个数据源
  46. 来访问一个假想的基于 JSON 远程 API我们会把它叫做 ``FarAwaySource``并把它
  47. 放在 ``app/Model/Datasource/FarAwaySource.php`` ::
  48. App::uses('HttpSocket', 'Network/Http');
  49. class FarAwaySource extends DataSource {
  50. /**
  51. * 数据源的描述,可省略
  52. */
  53. public $description = 'A far away datasource';
  54. /**
  55. * 缺省配置选项。这些选项会在 ``app/Config/database.php`` 中定制化,并且会在
  56. * ``__construct()`` 中合并。
  57. */
  58. public $config = array(
  59. 'apiKey' => '',
  60. );
  61. /**
  62. * 如果我们要 create() 或 update(),我们需要指定可用的字段。我们使用与在
  63. * CakeSchema 中一样的数组键,例如 fixtures 和 schema 升级。
  64. */
  65. protected $_schema = array(
  66. 'id' => array(
  67. 'type' => 'integer',
  68. 'null' => false,
  69. 'key' => 'primary',
  70. 'length' => 11,
  71. ),
  72. 'name' => array(
  73. 'type' => 'string',
  74. 'null' => true,
  75. 'length' => 255,
  76. ),
  77. 'message' => array(
  78. 'type' => 'text',
  79. 'null' => true,
  80. ),
  81. );
  82. /**
  83. * 创建 HttpSocket,处理任何配置调整。
  84. */
  85. public function __construct($config) {
  86. parent::__construct($config);
  87. $this->Http = new HttpSocket();
  88. }
  89. /**
  90. * 因为数据源通常连接到数据库,我们必须改变一些东西,才能使它适合没有数据库
  91. * 的情况。
  92. */
  93. /**
  94. * listSources() 用于缓存。在定制数据源中你可能会要用自己的方式实现缓存。
  95. * 所以只要 ``return null`` 就行了。
  96. */
  97. public function listSources($data = null) {
  98. return null;
  99. }
  100. /**
  101. * describe() 告诉模型你的 ``Model::save()`` 使用的 schema。
  102. *
  103. * 也许对你的每个模型都需要一个不同的 schema,但仍然使用一个数据源。如果是这
  104. * 样,那么在模型中设置一个 ``schema`` 属性,而从这里只返回
  105. * ``$model->schema``。
  106. */
  107. public function describe($model) {
  108. return $this->_schema;
  109. }
  110. /**
  111. * calculate() 用来决定如何对记录进行计数,要让 ``update()`` 和 ``delete()``
  112. * 正常工作这是必须的。
  113. *
  114. * 在这里我们不计数,而是返回一个字符串传给 ``read()``,让它(指 ``read()``)
  115. * 去做真正的计数。最容易的方法是只需返回字符串 'COUNT',然后在 ``read()``
  116. * 里面检查 ``$data['fields'] === 'COUNT'``。
  117. */
  118. public function calculate(Model $model, $func, $params = array()) {
  119. return 'COUNT';
  120. }
  121. /**
  122. * 实现 CRUD 中的 R。调用 ``Model::find()`` 时,会到达这里。
  123. */
  124. public function read(Model $model, $queryData = array(),
  125. $recursive = null) {
  126. /**
  127. * 这里我们按照上面 calculate() 方法的指示进行真正的计数。我们可以检
  128. * 查远程数据源,也可以用其它方法,来获得记录数。这里我们只是返回 1,
  129. * 这样 ``update()`` 和 ``delete()`` 就会认为记录存在。
  130. */
  131. if ($queryData['fields'] === 'COUNT') {
  132. return array(array(array('count' => 1)));
  133. }
  134. /**
  135. * 现在我们来获得远程数据,再将其解码并返回。
  136. */
  137. $queryData['conditions']['apiKey'] = $this->config['apiKey'];
  138. $json = $this->Http->get(
  139. 'http://example.com/api/list.json',
  140. $queryData['conditions']
  141. );
  142. $res = json_decode($json, true);
  143. if (is_null($res)) {
  144. $error = json_last_error();
  145. throw new CakeException($error);
  146. }
  147. return array($model->alias => $res);
  148. }
  149. /**
  150. * 实现 CRUD 中的 C。调用 ``Model::save()`` 时不设置 $model->id,会到达这里。
  151. */
  152. public function create(Model $model, $fields = null, $values = null) {
  153. $data = array_combine($fields, $values);
  154. $data['apiKey'] = $this->config['apiKey'];
  155. $json = $this->Http->post('http://example.com/api/set.json', $data);
  156. $res = json_decode($json, true);
  157. if (is_null($res)) {
  158. $error = json_last_error();
  159. throw new CakeException($error);
  160. }
  161. return true;
  162. }
  163. /**
  164. * 实现 CRUD 中的 U。调用 ``Model::save()`` 时设置了 $model->id,会到达这里。
  165. * 取决于远程数据源,你也许只需调用 ``$this->create()``。
  166. */
  167. public function update(Model $model, $fields = null, $values = null,
  168. $conditions = null) {
  169. return $this->create($model, $fields, $values);
  170. }
  171. /**
  172. * 实现 CRUD 中的 D。调用 ``Model::delete()`` 时,会到达这里。
  173. */
  174. public function delete(Model $model, $id = null) {
  175. $json = $this->Http->get('http://example.com/api/remove.json', array(
  176. 'id' => $id[$model->alias . '.id'],
  177. 'apiKey' => $this->config['apiKey'],
  178. ));
  179. $res = json_decode($json, true);
  180. if (is_null($res)) {
  181. $error = json_last_error();
  182. throw new CakeException($error);
  183. }
  184. return true;
  185. }
  186. }
  187. 接下去我们就可以在 ``app/Config/database.php`` 文件中添加下面的代码来配置数据
  188. ::
  189. public $faraway = array(
  190. 'datasource' => 'FarAwaySource',
  191. 'apiKey' => '1234abcd',
  192. );
  193. 然后象这样在模型中使用数据库配置::
  194. class MyModel extends AppModel {
  195. public $useDbConfig = 'faraway';
  196. }
  197. 我们可以用熟悉的模型方法从远程数据源获取数据::
  198. // 从'某人(Some Person)'获得全部消息
  199. $messages = $this->MyModel->find('all', array(
  200. 'conditions' => array('name' => 'Some Person'),
  201. ));
  202. .. tip::
  203. 如果 ``read`` 方法的结果不是一个数字下标的数组使用除 ``'all'`` 以外的其它
  204. find 类型会导致意想不到的结果
  205. 同样我们可以保存一条新消息::
  206. $this->MyModel->save(array(
  207. 'name' => 'Some Person',
  208. 'message' => 'New Message',
  209. ));
  210. 更新上一条消息::
  211. $this->MyModel->id = 42;
  212. $this->MyModel->save(array(
  213. 'message' => 'Updated message',
  214. ));
  215. 以及删除消息::
  216. $this->MyModel->delete(42);
  217. 插件的数据源
  218. ============
  219. 你也可以把数据源封装在插件之中
  220. 你只需把你的数据源文件放在
  221. ``Plugin/[YourPlugin]/Model/Datasource/[YourSource].php``然后用插件的语法引用
  222. ::
  223. public $faraway = array(
  224. 'datasource' => 'MyPlugin.FarAwaySource',
  225. 'apiKey' => 'abcd1234',
  226. );
  227. 连接 SQL Server
  228. ===============
  229. Sqlserver 数据源依赖于微软的名为 pdo_sqlsrv PHP 扩展该扩展未包含在 PHP 的基
  230. 本安装中必须单独安装
  231. 而且必须安装 SQL Server Native Client该扩展才能工作由于 Native Client 只适用
  232. Windows你无法在 LinuxMac OS X 或者 FreeBSD 上安装
  233. 所以如果 Sqlserver 数据源报如下错误::
  234. Error: Database connection "Sqlserver" is missing, or could not be created.
  235. 请首先检查是否正确安装了 SQL Server PHP 扩展 pdo_sqlsrv SQL Server Native
  236. Client
  237. .. meta::
  238. :title lang=zh: DataSources
  239. :keywords lang=zh: array values,model fields,connection configuration,implementation details,relational databases,best bet,mysql postgresql,sqlite,external sources,ldap server,database connection,rdbms,sqlserver,postgres,relational database,microsoft sql server,aggregates,apis,repository,signatures