#### Hydration Modes 水合模式
As mentioned previously, resultsets are collections of complete objects, this means that every returned result is an object representing a row in the database. These objects can be modified and saved again to persistence:
如前所述,resultset是完整對象的集合,這意味著每個返回的結果都是表示數據庫中的一行的對象。這些對象可以被修改并保存為持久性:
~~~
<?php
use Store\Toys\Robots;
$robots = Robots::find();
// Manipulating a resultset of complete objects
foreach ($robots as $robot) {
$robot->year = 2000;
$robot->save();
}
~~~
Sometimes records are obtained only to be presented to a user in read-only mode, in these cases it may be useful to change the way in which records are represented to facilitate their handling. The strategy used to represent objects returned in a resultset is called ‘hydration mode’:
有時,只有在只讀模式下才能將記錄顯示給用戶,在這種情況下,更改記錄的表示方式以方便處理是很有用的。用于表示結果集返回的對象的策略稱為“水合模式”:
~~~
<?php
use Phalcon\Mvc\Model\Resultset;
use Store\Toys\Robots;
$robots = Robots::find();
// Return every robot as an array
$robots->setHydrateMode(
Resultset::HYDRATE_ARRAYS
);
foreach ($robots as $robot) {
echo $robot["year"], PHP_EOL;
}
// Return every robot as a stdClass
$robots->setHydrateMode(
Resultset::HYDRATE_OBJECTS
);
foreach ($robots as $robot) {
echo $robot->year, PHP_EOL;
}
// Return every robot as a Robots instance
$robots->setHydrateMode(
Resultset::HYDRATE_RECORDS
);
foreach ($robots as $robot) {
echo $robot->year, PHP_EOL;
}
~~~
Hydration mode can also be passed as a parameter of ‘find’:
水合模式也可以作為“find”的參數傳遞:
~~~
<?php
use Phalcon\Mvc\Model\Resultset;
use Store\Toys\Robots;
$robots = Robots::find(
[
"hydration" => Resultset::HYDRATE_ARRAYS,
]
);
foreach ($robots as $robot) {
echo $robot["year"], PHP_EOL;
}
~~~
#### 自動生成標識列(Auto-generated identity columns)
Some models may have identity columns. These columns usually are the primary key of the mapped table. Phalcon\Mvc\Model can recognize the identity column omitting it in the generated SQL INSERT, so the database system can generate an auto-generated value for it. Always after creating a record, the identity field will be registered with the value generated in the database system for it:
有些模型可能有標識列。這些列通常是映射表的主鍵。在生成的SQL INSERT中,可以識別出身份列的標識列,因此數據庫系統可以為它生成自動生成的值。在創建記錄之后,標識字段將以數據庫系統中生成的值進行注冊:
~~~
<?php
$robot->save();
echo "The generated id is: ", $robot->id;
~~~
Phalcon\Mvc\Model is able to recognize the identity column. Depending on the database system, those columns may be serial columns like in PostgreSQL or auto_increment columns in the case of MySQL.
在這個問題上,Phalcon\Mvc\Model能夠識別身份欄。根據數據庫系統的不同,這些列可能是像PostgreSQL或MySQL這樣的自動增量列的串行列。
PostgreSQL uses sequences to generate auto-numeric values, by default, Phalcon tries to obtain the generated value from the sequence “table_field_seq”, for example: robots_id_seq, if that sequence has a different name, the `getSequenceName()` method needs to be implemented:
PostgreSQL使用序列來生成自動數字值,在默認情況下,Phalcon試圖從序列“tablefieldseq”中獲得生成的值,例如:如果這個序列有一個不同的名字,`getSequenceName()`方法需要實現:
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function getSequenceName()
{
return "robots_sequence_name";
}
}
~~~
#### 忽略指定列的數據(Skipping Columns)
To tell Phalcon\Mvc\Model that always omits some fields in the creation and/or update of records in order to delegate the database system the assignation of the values by a trigger or a default:
為了告訴To tell Phalcon\Mvc\Model在創建和/或更新記錄的時候,總是省略一些字段,以便將數據庫系統委派給一個觸發器或默認值
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function initialize()
{
// Skips fields/columns on both INSERT/UPDATE operations
$this->skipAttributes(
[
"year",
"price",
]
);
// Skips only when inserting
$this->skipAttributesOnCreate(
[
"created_at",
]
);
// Skips only when updating
$this->skipAttributesOnUpdate(
[
"modified_in",
]
);
}
}
~~~
This will ignore globally these fields on each INSERT/UPDATE operation on the whole application. If you want to ignore different attributes on different INSERT/UPDATE operations, you can specify the second parameter (boolean) - true for replacement. Forcing a default value can be done in the following way:
在整個應用程序的每次插入/更新操作中,都會忽略全局這些字段。如果您想忽略不同的插入/更新操作的不同屬性,可以指定第二個參數(boolean)-true用于替換。強制默認值可以按照以下方式進行:
~~~
<?php
use Store\Toys\Robots;
use Phalcon\Db\RawValue;
$robot = new Robots();
$robot->name = "Bender";
$robot->year = 1999;
$robot->created_at = new RawValue("default");
$robot->create();
~~~
A callback also can be used to create a conditional assignment of automatic default values:
還可以使用回調來創建自動默認值的條件賦值:
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
use Phalcon\Db\RawValue;
class Robots extends Model
{
public function beforeCreate()
{
if ($this->price > 10000) {
$this->type = new RawValue("default");
}
}
}
~~~
* * * * *
> Never use a Phalcon\Db\RawValue to assign external data (such as user input) or variable data. The value of these fields is ignored when binding parameters to the query. So it could be used to attack the application injecting SQL.
>永遠不要使用一個 Phalcon\Db\RawValue參數值來分配外部數據(例如用戶輸入)或變量數據。在將參數綁定到查詢時,這些字段的值會被忽略。因此,它可以用來攻擊應用程序注入SQL。
* * * * *
#### 動態更新(Dynamic Update)
SQL UPDATE statements are by default created with every column defined in the model (full all-field SQL update). You can change specific models to make dynamic updates, in this case, just the fields that had changed are used to create the final SQL statement.
默認情況下,SQL UPDATE語句是在模型中定義的每個列創建的(完整的字段SQL更新)。您可以更改特定的模型來進行動態更新,在本例中,只是使用了更改的字段來創建最終的SQL語句。
In some cases this could improve the performance by reducing the traffic between the application and the database server, this specially helps when the table has blob/text fields:
在某些情況下,這可以通過減少應用程序和數據庫服務器之間的通信來提高性能,這在表有blob/text字段時特別有用。
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function initialize()
{
$this->useDynamicUpdate(true);
}
}
~~~
#### 獨立的列映射(Independent Column Mapping)
The ORM supports an independent column map, which allows the developer to use different column names in the model to the ones in the table. Phalcon will recognize the new column names and will rename them accordingly to match the respective columns in the database. This is a great feature when one needs to rename fields in the database without having to worry about all the queries in the code. A change in the column map in the model will take care of the rest. For example:
ORM支持獨立的列映射,這允許開發人員在模型中使用不同的列名。為了匹配數據庫中相應的列,它將識別新的列名,并相應地對其進行重命名。當需要重命名數據庫中的字段而不必擔心代碼中的所有查詢時,這是一個很好的特性。模型中列映射的更改將處理其余部分。例如:
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public $code;
public $theName;
public $theType;
public $theYear;
public function columnMap()
{
// Keys are the real names in the table and
// the values their names in the application
return [
"id" => "code",
"the_name" => "theName",
"the_type" => "theType",
"the_year" => "theYear",
];
}
}
~~~
Then you can use the new names naturally in your code:
然后你可以在你的代碼中自然地使用這些新名字:
~~~
<?php
use Store\Toys\Robots;
// Find a robot by its name
$robot = Robots::findFirst(
"theName = 'Voltron'"
);
echo $robot->theName, "\n";
// Get robots ordered by type
$robot = Robots::find(
[
"order" => "theType DESC",
]
);
foreach ($robots as $robot) {
echo "Code: ", $robot->code, "\n";
}
// Create a robot
$robot = new Robots();
$robot->code = "10101";
$robot->theName = "Bender";
$robot->theType = "Industrial";
$robot->theYear = 2999;
$robot->save();
~~~
Take into consideration the following the next when renaming your columns:
在重新命名您的列時,請考慮以下內容:
* References to attributes in relationships/validators must use the new names
關系/驗證器中的屬性引用必須使用新名稱
* Refer the real column names will result in an exception by the ORM
引用實際的列名將導致ORM出現異常
The independent column map allow you to:
獨立的列映射允許您這樣做:
* Write applications using your own conventions
使用您自己的約定編寫應用程序
* Eliminate vendor prefixes/suffixes in your code
在您的代碼中消除供應商前綴/后綴
* Change column names without change your application code
更改列名,而不更改應用程序代碼
#### 記錄快照(Record Snapshots)
Specific models could be set to maintain a record snapshot when they’re queried. You can use this feature to implement auditing or just to know what fields are changed according to the data queried from the persistence:
可以設置特定的模型,以便在查詢時保持記錄快照。您可以使用這個特性來實現審計,或者僅僅根據從持久性中查詢的數據來了解哪些字段被更改了。
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function initialize()
{
$this->keepSnapshots(true);
}
}
~~~
When activating this feature the application consumes a bit more of memory to keep track of the original values obtained from the persistence. In models that have this feature activated you can check what fields changed:
當激活該特性時,應用程序會消耗更多的內存來跟蹤從持久性中獲得的原始值。在具有該特性的模型中,您可以檢查哪些字段發生了變化:
~~~
<?php
use Store\Toys\Robots;
// Get a record from the database
$robot = Robots::findFirst();
// Change a column
$robot->name = "Other name";
var_dump($robot->getChangedFields()); // ["name"]
var_dump($robot->hasChanged("name")); // true
var_dump($robot->hasChanged("type")); // false
~~~
#### 設置模式(Pointing to a different schema)
如果一個模型映射到一個在非默認的schemas/數據庫中的表,你可以通過 `setSchema()` 方法去定義它:
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function initialize()
{
$this->setSchema("toys");
}
}
~~~
#### 設置多個數據庫(Setting multiple databases)
在Phalcon中,所有模型可以屬于同一個數據庫連接,也可以分屬獨立的數據庫連接。實際上,當 Phalcon\Mvc\Model 需要連接數據庫的時候,它在應用服務容器內請求”db”這個服務。 可以通過在` initialize()` 方法內重寫這個服務的設置。
~~~
<?php
use Phalcon\Db\Adapter\Pdo\Mysql as MysqlPdo;
use Phalcon\Db\Adapter\Pdo\PostgreSQL as PostgreSQLPdo;
// This service returns a MySQL database
$di->set(
"dbMysql",
function () {
return new MysqlPdo(
[
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo",
]
);
}
);
// This service returns a PostgreSQL database
$di->set(
"dbPostgres",
function () {
return new PostgreSQLPdo(
[
"host" => "localhost",
"username" => "postgres",
"password" => "",
"dbname" => "invo",
]
);
}
);
~~~
然后,在` initialize() `方法內,我們為這個模型定義數據庫連接。
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function initialize()
{
$this->setConnectionService("dbPostgres");
}
}
~~~
另外Phalcon還提供了更多的靈活性,你可分別定義用來讀取和寫入的數據庫連接。這對實現主從架構的數據庫負載均衡非常有用。 (譯者注:EvaEngine項目為使用Phalcon提供了更多的靈活性,推薦了解和使用)
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function initialize()
{
$this->setReadConnectionService("dbSlave");
$this->setWriteConnectionService("dbMaster");
}
}
~~~
另外ORM還可以通過根據當前查詢條件來實現一個 ‘shard’ 選擇器,來實現水平切分的功能。
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
/**
* Dynamically selects a shard
*
* @param array $intermediate
* @param array $bindParams
* @param array $bindTypes
*/
public function selectReadConnection($intermediate, $bindParams, $bindTypes)
{
// Check if there is a 'where' clause in the select
if (isset($intermediate["where"])) {
$conditions = $intermediate["where"];
// Choose the possible shard according to the conditions
if ($conditions["left"]["name"] === "id") {
$id = $conditions["right"]["value"];
if ($id > 0 && $id < 10000) {
return $this->getDI()->get("dbShard1");
}
if ($id > 10000) {
return $this->getDI()->get("dbShard2");
}
}
}
// Use a default shard
return $this->getDI()->get("dbShard0");
}
}
~~~
`selectReadConnection()` 方法用來選擇正確的數據庫連接,這個方法攔截任何新的查詢操作:
~~~
<?php
use Store\Toys\Robots;
$robot = Robots::findFirst('id = 101');
~~~
#### 注入服務到模型(Injecting services into Models)
你可能需要在模型中用到應用中注入的服務,下面的例子會教你如何去做:
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function notSaved()
{
// Obtain the flash service from the DI container
$flash = $this->getDI()->getFlash();
$messages = $this->getMessages();
// Show validation messages
foreach ($messages as $message) {
$flash->error($message);
}
}
}
~~~
每當 “create” 或者 “update” 操作失敗時會觸發 “notSave” 事件。所以我們從DI中獲取 “flash” 服務并推送確認消息。這樣的話,我們不需要每次在save之后去打印信息。
#### 禁用或啟用特性(Disabling/Enabling Features)
In the ORM we have implemented a mechanism that allow you to enable/disable specific features or options globally on the fly. According to how you use the ORM you can disable that you aren’t using. These options can also be temporarily disabled if required:
在ORM中,我們已經實現了一種機制,允許您在全局范圍內啟用/禁用特定的特性或選項。根據您如何使用ORM,您可以禁用您不使用的ORM。如果需要,這些選項也可以臨時禁用:
~~~
<?php
use Phalcon\Mvc\Model;
Model::setup(
[
"events" => false,
"columnRenaming" => false,
]
);
~~~
The available options are:
可用的選項是:
| Option |Description 描述 | Default |
| --- | --- | --- |
| events | Enables/Disables callbacks, hooks and event notifications from all the models 從所有模型中啟用/禁用回調、鉤子和事件通知 | `true` |
| columnRenaming | columnRenaming 修改字段名字 | `true` |
| notNullValidations | The ORM automatically validate the not null columns present in the mapped table ORM 自動驗證映射表中存在的not null列 | `true` |
| virtualForeignKeys | Enables/Disables the virtual foreign keys 啟用/禁用虛擬外鍵 | `true` |
| phqlLiterals | Enables/Disables literals in the PHQL parser 在PHQL解析器中啟用/禁用文本 | `true` |
|lateStateBinding | Enables/Disables late state binding of the `Mvc\Model::cloneResultMap()` method 啟用/禁用Mvc模型的后期綁定::cloneResultMap()的方法 | `false` |
#### 獨立的組件(Stand-Alone component)
Using Phalcon\Mvc\Model in a stand-alone mode can be demonstrated below:
在一個獨立的模式下使用 Phalcon\Mvc\Model 可以在下面演示:
~~~
<?php
use Phalcon\Di;
use Phalcon\Mvc\Model;
use Phalcon\Mvc\Model\Manager as ModelsManager;
use Phalcon\Db\Adapter\Pdo\Sqlite as Connection;
use Phalcon\Mvc\Model\Metadata\Memory as MetaData;
$di = new Di();
// Setup a connection
$di->set(
"db",
new Connection(
[
"dbname" => "sample.db",
]
)
);
// Set a models manager
$di->set(
"modelsManager",
new ModelsManager()
);
// Use the memory meta-data adapter or other
$di->set(
"modelsMetadata",
new MetaData()
);
// Create a model
class Robots extends Model
{
}
// Use the model
echo Robots::count();
~~~
- Welcome
- 安裝
- XAMPP 下的安裝
- WAMP 下安裝
- Apache 安裝說明
- Nginx 安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程6: V?kuró
- 教程 7:創建簡單的 REST API
- 依賴注入與服務定位器(Dependency Injection/Service Location)
- MVC 架構(The MVC Architecture)
- 使用控制器(Using Controllers)
- 使用模型(Working with Models)
- 模型關系(Model Relationships)
- 模型事件(Model Events)
- 模型行為(Model Behaviors)
- 模型元數據(Models Metadata)
- 事務管理(Model Transactions)
- 模型驗證(Validating Models)
- Working with Models (Advanced)
- Phalcon 查詢語言(Phalcon Query Language (PHQL))
- 緩存對象關系映射(Caching in the ORM)
- 對象文檔映射 ODM (Object-Document Mapper)
- 使用視圖(Using Views)
- 視圖助手 (Tags)(View Helpers (Tags))