摘要:使用模型模型表示應用程序信息數據以及這些數據的處理規則,主要用于管理與對應數據表的交互規則。應用中,是所有模型的基類。創建模型模型需繼承類,以大駝峰格式命名。方法在請求期間只調用一次,目的是為該模型的所有實例執行初始化操作。
使用模型(Working with Models)
模型表示應用程序信息(數據)以及這些數據的處理規則,主要用于管理與對應數據表的交互規則。大多數情況下,數據庫中的每一張表都有對應的模型。應用程序中的大部分業務邏輯集中在模型中。
Phalcon應用中,PhalconMvcModel是所有模型的基類。它提供了數據庫獨立、基礎CRUD、高級查找、模型關聯以及其他服務。
PhalconMvcModel將調用的方法動態轉換為相應的數據庫操作,避免了直接使用SQL。
模型使用數據庫高級抽象層,如果想要使用更為底層的方式操作數據庫,請參考PhalconDb組件文檔。
創建模型(Creating Models)模型需繼承PhalconMvcModel類,以大駝峰格式命名。
如果使用PHP 5.4、5.5版本,建議在模型中聲明對應數據表的所有字段,以節約內存。
模型StoreToysRobotParts默認映射robot_parts表,可以調用setSource()方法手動指定映射表:
setSource("toys_robot_parts"); } }模型RobotParts現在映射toys_robot_parts表。initialize()方法有助于在模型中創建自定義行為,如為模型指定映射表。
initialize()方法在請求期間只調用一次,目的是為該模型的所有實例執行初始化操作。如果每次實例化模型的時候都需要進行初始化,可以使用onConstruct()方法:
公共屬性和Setters、Getters方法(Public properties vs. Setters/Getters)模型可以定義公共屬性,在任何獲取了模型實例的地方都可以讀寫模型的公共屬性:
另一種實現方式是getters和setters方法,控制哪些模型屬性可以公開訪問。這種方式的好處是,開發者可以在對模型屬性進行寫操作時執行轉換和驗證,這是使用公共屬性方式無法實現的。此外,getters和setters可以在不改動模型和接口的前提下,應對未來可能的改動。如果字段名稱改變,唯一需要的改動的地方是getters和setters中引用的模型私有屬性。
id; } public function setName($name) { // name不能太短 if (strlen($name) < 10) { throw new InvalidArgumentException( "The name is too short" ); } $this->name = $name; } public function getName() { return $this->name; } public function setPrice($price) { // price不能為負 if ($price < 0) { throw new InvalidArgumentException( "Price can"t be negative" ); } $this->price = $price; } public function getPrice() { // 返回前,將該值轉換為double類型 return (double) $this->price; } }雖然公共屬性在開發中的復雜度更低,但是getters和setters可以大大提高程序的測試性、擴展性和可維護性。開發者可以根據需求決定哪種方式更適合他們的應用。ORM兼容這兩種方式。
使用getters和setters時,屬性名中的下劃線可能會導致問題。
如果在屬性名中使用下劃線,在聲明getters和setters魔術方法時,仍然要使用駝峰格式($model->getPropertyName()代替$model->getProperty_name(),$model->findByPropertyName()代替$model->findByProperty_name()等)。大多數系統推薦駝峰寫法,而不是下劃線寫法,所以建議按照文檔中的寫法為屬性命名??梢允褂米侄斡成?如上所述)以確保屬性正確映射到數據表中對應字段。
理解記錄對象(Understanding Records To Objects)模型的每一個實例代表數據表中的一條記錄,可以通過讀取模型對象屬性來訪問記錄數據。例如,表robots有如下記錄:
mysql> select * from robots; +----+------------+------------+------+ | id | name | type | year | +----+------------+------------+------+ | 1 | Robotina | mechanical | 1972 | | 2 | Astro Boy | mechanical | 1952 | | 3 | Terminator | cyborg | 2029 | +----+------------+------------+------+ 3 rows in set (0.00 sec)通過主鍵查找某條記錄:
name;一旦記錄存儲在內存中,就可以修改其中的數據并保存:
name = "RoboCop"; $robot->save();PhalconMvcModel為web應用提供了數據庫高級抽象層,不需要使用原生SQL語句。
查找記錄(Finding Records)PhalconMvcModel提供了多種查詢記錄的方法,下面例子演示如何用模型查找一條或多條記錄:
"name", ] ); foreach ($robots as $robot) { echo $robot->name, " "; } // 獲取type = "virtual"的前100條記錄,根據name排序 $robots = Robots::find( [ "type = "virtual"", "order" => "name", "limit" => 100, ] ); foreach ($robots as $robot) { echo $robot->name, " "; }如果要使用外部數據(如用戶輸入)或變量查找記錄,必須進行參數綁定。
使用findFirst()方法,獲取滿足給定條件的第一條記錄:
name, " "; // 獲取robots表中type = "mechanical"的第一條記錄 $robot = Robots::findFirst("type = "mechanical""); echo "The first mechanical robot name is ", $robot->name, " "; // 獲取robots表中type = "virtual"的第一條記錄,根據name排序 $robot = Robots::findFirst( [ "type = "virtual"", "order" => "name", ] ); echo "The first virtual robot name is ", $robot->name, " ";find()方法和findFirst()方法都接受一個包含指定搜索條件的關聯數組:
"name DESC", "limit" => 30, ] ); $robots = Robots::find( [ "conditions" => "type = ?1", "bind" => [ 1 => "virtual", ], ] );有下列查詢選項:
參數 | 說明 | 示例 |
---|---|---|
conditions | 查詢操作的搜索條件,用于篩選符合指定條件的記錄。默認情況下,PhalconMvcModel假定第一個參數就是搜索條件 | "conditions" => "name LIKE "steve%"" |
columns | 獲取模型中的指定字段,而不是所有字段。使用此選項時,返回不完整對象。 | "columns" => "id, name" |
bind | 參數綁定與conditions一起使用,通過替換占位符、轉義特殊字符從而提高安全性 | "bind" => ["status" => "A", "type" => "some-time"] |
bindTypes | 使用參數綁定時,可以使用這個參數為綁定參數定義額外的類型限制,從而提高安全性 | "bindTypes" => [Column::BIND_PARAM_STR, Column::BIND_PARAM_INT] |
order | 用于對結果集進行排序,使用逗號分隔多個字段 | "order" => "name DESC, status" |
limit | 將查詢結果的數量限制在一定范圍內 | "limit" => 10 |
offset | 設定查詢結果偏移量 | "offset" => 5 |
group | 允許跨記錄收集數據,并將結果集按一個或多個字段分組 | "group" => "name, status" |
for_update | 使用此選項,PhalconMvcModel將讀取最新的可用數據,并為讀取到的每一條記錄設置獨占鎖 | "for_update" => true |
shared_lock | 使用此選項,PhalconMvcModel將讀取最新的可用數據,并為讀取到的每一條記錄設置共享鎖 | "shared_lock" => true |
cache | 緩存結果集,減少對數據庫的持續訪問 | "cache" => ["lifetime" => 3600, "key" => "my-find-key"] |
hydration | 設置結果集返回模式 | "hydration" => Resultset::HYDRATE_OBJECTS |
除了使用參數數組,還可以使用面向對象的方式創建查詢:
where("type = :type:") ->addWhere("year < 2000") ->bind(["type" => "machanical"]) ->order("name") ->execute();
靜態方法query()返回一個IDE自動完成友好的PhalconMvcModelCriteria對象。
所有查詢在內部都以PHQL查詢的方式處理。PHQL是一種高級的、面向對象的類SQL語言,這種語言提供了多種功能來執行查詢,如join其他模型,定義分組,添加聚合等。
最后,還有一個findFirstBy
這里有三個屬性:$id,$name和$price,假設要檢索name為"Terminator"的第一條記錄,代碼如下:
price, "."; } else { echo "There were no robots found in our table with the name " . $name . "."; }請注意,我們在調用的方法中使用了Name并傳遞了變量$name,表中name字段值為$name的記錄就是我們要查找的。
模型結果集(Model Resultsets)findFirst()方法返回被調用類的實例(如果有結果返回),而find()方法返回PhalconMvcModelResultsetsSimple對象,該對象封裝了結果集應有的所有功能,如遍歷,查找特定記錄,統計等。
這些對象比一般數組功能強大,PhalconMvcModelResultset一個最大的特點是,任何時刻,只有一條記錄保存在內存中。這對內存管理有極大幫助,特別是在處理大批量數據時。
name, " "; } // while遍歷 while ($robots->valid()) { $robot = $robots->current(); echo $robot->name, " "; $robots->next(); } // 結果集計數 echo count($robots); // 另一種結果集計數方法 echo $robots->count(); // 移動游標到第三條記錄 $robots->seek(2); $robot = $robots->current(); // 通過位置訪問結果集中的記錄 $robot = $robots[5]; // 檢查指定位置是否有記錄 if (isset($robots[3])) { $robot = $robots[3]; } // 獲取結果集中第一條記錄 $robot = $robots->getFirst(); // 獲取結果集中最后一條記錄 $robot = $robots->getLast();Phalcon結果集模擬游標,可以通過訪問其位置或內部指針獲取任一條記錄。注意,某些數據庫系統不支持游標,這會導致查詢被反復執行,以重置游標到初始位置并獲取被請求位置的記錄。同樣的,遍歷多少次結果集,查詢便要執行多少次。
將大量查詢結果保存在內存中會消耗太多資源,因此,在某些情況下,以32條記錄為一塊從數據庫中獲取記錄,可以降低重復執行請求的內存消耗。
注意,結果集可以序列化后存儲在緩存中,PhalconCache可以實現該需求。但是序列化數據會導致PhalconMvcModel以數組形式保存從數據庫中檢索到的數據,這會導致更多的內存消耗。
id; }自定義結果集(Custom Resultsets)有時候應用程序需要對數據庫中檢索到的數據進行額外處理。以前,我們只需要擴展模型或將功能封裝在模型或trait當中,然后返回一組經過轉換的數據。
通過自定義結果集,不需要再如此處理。自定義結果集將封裝原本封裝在模型中并能被其他模型重用的功能,這樣可以簡化代碼。如此,find()方法返回自定義對象,而不再返回PhalconMvcModelResultset對象。Phalcon允許在模型中定義getResultsetClass()方法來實現此操作。
首先,聲明resultset類:
模型中,在getResultsetClass()方法里設置resultset類,如下:
最后,代碼里應包含如下內容:
"date between "2017-01-01" AND "2017-12-31"", "order" => "date", ] ); /** * 傳遞數據到視圖 */ $this->view->mydata = $robots->getSomeData();過濾結果集(Filtering Resultsets)過濾數據最有效的方法之一是設置搜索條件,數據庫將使用表索引以更快的返回數據。Phalcon允許使用PHP函數或是數據庫不支持的方式過濾數據:
filter( function ($customer) { // 只返回e-mail合法的記錄 if (filter_var($customer->email, FILTER_VALIDATE_EMAIL)) { return $customer; } } );參數綁定(Binding Parameters)PhalconMvcModel支持參數綁定,建議使用這種方法以避免SQL注入,字符串占位符和數字占位符均被支持。參數綁定簡單實現如下:
[ "name" => "Robotina", "type" => "maid", ], ] ); // 數字占位符 $robots = Robots::find( [ "name = ?1 AND type = ?2", "bind" => [ 1 => "Robotina", 2 => "maid", ], ] ); // 同時使用字符串占位符和數字占位符 $robots = Robots::find( [ "name = :name: AND type = ?1", "bind" => [ "name" => "Robotina", 1 => "maid", ], ] );使用數字占位符時,需要將它們定義成整數形式,即1或2。而"1"或"2"會被當成字符串,所以占位符不能被成功替換。
字符串會自動使用PDO轉義,該功能會考慮連接字符集,因此建議在連接參數或數據庫配置中定義正確字符集,因為錯誤字符集會在存儲和檢索數據時產生不良影響。
還可以設置bindTypes參數,定義參數如何根據其類型綁定:
"Robotina", "year" => 2008, ]; // 參數類型轉換 $types = [ "name" => Column::BIND_PARAM_STR, "year" => Column::BIND_PARAM_INT, ]; // 字符串占位符 $robots = Robots::find( [ "name = :name: AND year = :year:", "bind" => $parameters, "bindTypes" => $types, ] );由于默認的綁定類型是PhalconDbColumn::BIND_PARAM_STR,如果所有字段都是字符串類型,則沒有必要指定bindTypes參數。
如果使用數組作為綁定參數,則數組必須是鍵名從0開始的索引數組:
"a", [1] => "b", [2] => "c"] unset($array[1]); // $array: [[0] => "a", [2] => "c"] // 現在必須重建數組索引 $array = array_values($array); // $array: [[0] => "a", [1] => "c"] $robots = Robots::find( [ "letter IN ({letter:array})", "bind" => [ "letter" => $array, ], ] );參數綁定除了可用于所有查詢方法,如find()和findFirst()外,還可用于count(),sum(),average()等統計方法。
使用finders時,會自動使用參數綁定:
[ "Ultron", ], ] ); // 隱式使用參數綁定 $robots = Robots::findByName("Ultron");初始化已獲取記錄(Initializing / Preparing fetched records)有時從數據庫獲取記錄之后,在數據被應用程序使用之前,需要對數據進行初始化。可以在模型中實現afterFetch()方法,實例化模型時會執行該方法,并將數據傳遞給它:
status = join(",", $this->status); } public function afterFetch() { // 將字符串轉換成數組 $this->status = explode(",", $this->status); } public function afterSave() { // 將字符串轉換成數組 $this->status = explode(",", $this->status); } }如果使用getters/setters代替公共屬性,或同時使用它們,可以在字段被訪問時初始化字段:
status); } }生成運算(Generating Calculations)運算(或聚合)是數據庫中常用的輔助方法,如COUNT,SUM,MAX,MIN和AVG。PhalconMvcModel可以直接使用這些方法。
Count示例:"area", ] ); // 表employees共有多少area為"Testing"的記錄 $rowcount = Employees::count( "area = "Testing"" ); // 按area分組統計表employees記錄 $group = Employees::count( [ "group" => "area", ] ); foreach ($group as $row) { echo "There are ", $row->rowcount, " in ", $row->area; } // 按area分組統計表employees記錄,并根據數目排序 $group = Employees::count( [ "group" => "area", "order" => "rowcount", ] ); // 使用參數綁定避免SQL注入 $group = Employees::count( [ "type > ?0", "bind" => [ $type, ], ] );Sum示例:
"salary", ] ); // area = "Sales"的所有employees的salaries總和 $total = Employees::sum( [ "column" => "salary", "conditions" => "area = "Sales"", ] ); // 根據area分組統計salaries $group = Employees::sum( [ "column" => "salary", "group" => "area", ] ); foreach ($group as $row) { echo "The sum of salaries of the ", $row->area, " is ", $row->sumatory; } // 根據area分組統計salaries,salaries由高到低排序 $group = Employees::sum( [ "column" => "salary", "group" => "area", "order" => "sumatory DESC", ] ); // 使用參數綁定避免參數綁定 $group = Employees::sum( [ "conditions" => "area > ?0", "bind" => [ $area, ], ] );Average示例:
"salary", ] ); // area = "Sales"的employees的平均salary $average = Employees::average( [ "column" => "salary", "conditions" => "area = "Sales"", ] ); // 使用參數綁定避免SQL注 $average = Employees::average( [ "column" => "age", "conditions" => "area > ?0", "bind" => [ $area, ], ] );Max / Min示例:
"age", ] ); // area = "Sales"的employees中age最大的 $age = Employees::maximum( [ "column" => "age", "conditions" => "area = "Sales"", ] ); // 所有employees中salary最低的 $salary = Employees::minimum( [ "column" => "salary", ] );創建 / 更新記錄(Creating / Updating Records)PhalconMvcModel::save()方法會根據記錄是否存在于模型映射表中而創建 / 更新記錄,PhalconMvcModel的創建和更新方法會在內部調用該方法。為此,必須在實體中正確定義主鍵,以確定是創建記錄還是更新記錄。
該方法會執行相關驗證器,虛擬外鍵和模型中定義的事件:
type = "mechanical"; $robot->name = "Astro Boy"; $robot->year = 1952; if ($robot->save() === false) { echo "Umh, We can"t store robots right now: "; $messages = $robot->getMessages(); foreach ($messages as $message) { echo $message, " "; } } else { echo "Great, a new robot was saved successfully!"; }直接傳遞或者通過屬性數組傳遞的值會根據其數據類型自動被轉義 / 過濾,所以可以傳遞一個不安全的數組而不用擔心SQL注入:
save($_POST);毫無防護的批量傳值可能會允許攻擊者設置任意字段的值,僅在允許用戶插入 / 更新模型中所有字段的情況下使用上述功能,即使這些字段不是使用表單提交的。
可以在save()方法中設置額外參數,以設置批量傳值時,執行插入 / 更新操作的白名單字段。
save( $_POST, [ "name", "type", ] );創建 / 更新執行結果(Create / Update with Confidence)應用程序高并發時,創建記錄操作可能會變成更新操作。使用PhalconMvcModel::save()方法保存記錄時,可能發生這種情況。如果想確保執行創建或更新,可以使用create()和update()方法替換save():
type = "mechanical"; $robot->name = "Astro Boy"; $robot->year = 1952; // 僅創建記錄 if ($robot->create() === false) { echo "Umh, We can"t store robots right now: "; $messages = $robot->getMessages(); foreach ($messages as $message) { echo $message, " "; } } else { echo "Great, a new robot was created successfully!"; }create()方法和update()方法同樣接受一個數組作為參數。
刪除記錄(Deleting Records)PhalconMvcModel::delete()方法允許刪除記錄,使用示例:
delete() === false) { echo "Sorry, we can"t delete the robot right now: "; $messages = $robot->getMessages(); foreach ($messages as $message) { echo $message, " "; } } else { echo "The robots was deleted successfully!"; } }也可以通過使用foreach遍歷結果集來刪除多條記錄:
delete() === false) { echo "Sorry, we can"t delete the robot right now: "; $messages = $robot->getMessages(); foreach ($messages as $message) { echo $message, " "; } } else { echo "The robot was deleted successfully!"; } }以下事件可以用于定義在執行刪除操作時,要執行的自定義業務規則:
操作 | 事件名稱 | 能否終止操作 | 說明 |
---|---|---|---|
刪除 | afterDelete | 否 | 刪除操作后執行 |
刪除 | beforeDelete | 是 | 刪除操作前執行 |
通過上述事件,可以在模型中定義業務規則:
status === "A") { echo "The robot is active, it can"t be deleted"; return false; } return true; } }Hydrations模式(Hydration Modes)
如前所述,結果集是完整對象的集合,這意味著每條返回結果都是一個對象,代表數據表中的一行。這些對象可以修改并永久保存:
year = 2000; $robot->save(); }
有時記錄只能以只讀模式呈現給用戶,這種情況下,改變記錄的展現方式有助于用戶處理數據。用于表示結果集中返回的對象的策略稱為"hydration mode":
setHydrateMode( Resultset::HYDRATE_ARRAYS ); foreach ($robots as $robot) { echo $robot["year"], PHP_EOL; } // 返回stdClass對象 $robots->setHydrateMode( Resultset::HYDRATE_OBJECTS ); foreach ($robots as $robot) { echo $robot->year, PHP_EOL; } // 返回模型實例 $robots->setHydrateMode( Resultset::HYDRATE_RECORDS ); foreach ($robots as $robot) { echo $robot->year, PHP_EOL; }
Hydration mode也可以作為find()方法的參數傳遞:
Resultset::HYDRATE_ARRAYS, ] ); foreach ($robots as $robot) { echo $robot["year"], PHP_EOL; }表前綴(Table prefixes)
如果希望所有表名稱都有特定前綴,并且不想在每個模型中都調用setSource()方法,則可以調用PhalconMvcModelManager的setModelprefix()方法:
setModelPrefix("wp_"); $robots = new Robots(null, null, $manager); echo $robots->getSource(); // 返回wp_robots自動生成的標識字段(Auto-generated identity columns)
某些模型有標識字段,這些字段通常是映射表的主鍵。PhalconMvcModel能夠識別標識字段,并在生成INSERT語句時忽略它,所以數據庫能夠自動為它生成一個值。創建記錄之后,標識字段的值會被注冊為數據庫為其生成的值:
save(); echo "The generated id is: ", $robot->id;
PhalconMvcModel能夠識別標識字段,根據數據庫系統,這些字段可能是PostgreSQL的串行列,或者是MySQL的自增列。
PostgreSQL使用序列生成自增值,默認情況下,Phalcon試圖從序列table_field_seq中獲取生成的值,例如:robots_id_seq,如果序列具有其他名稱,則需要實現getSequenceName()方法:
忽略字段(Skipping Columns)為PhalconMvcModel指定創建 / 更新記錄時需要被忽略的字段,以便數據庫為其賦默認值:
skipAttributes( [ "year", "price", ] ); // INSERT操作忽略字段 $this->skipAttributes( [ "created_at", ] ); // UPDATE操作忽略字段 $this->skipAttributes( [ "modified_in", ] ); } }這將全局忽略應用程序中每個INSERT / UPDATE操作的這些字段。如果想在不同的INSERT / UPDATE操作時忽略不同字段,可以傳遞第二個參數(布爾值) - true。強制使用默認值,實現方式如下:
name = "Bender"; $robot->year = 1999; $robot->created_at = new RawValue("default"); $robot->create();回調函數也可以用于為默認值創建分配條件:
price > 10000) { $this->type = new RawValue("default"); } } }切勿使用PhalconDbRawValue傳遞外部數據(如用戶輸入)或可變數據,因為參數綁定時,這些字段的值也會被忽略,所以有可能會被用來實施注入攻擊。
動態更新(Dynamic Updates)UPDATE語句默認使用模型中定義的所有字段創建(全字段更新SQL),可以更改特定模型以進行動態更新,用需要更新的字段創建SQL語句。
useDynamicUpdate(true); } }獨立列映射(Independent Column Mapping)ORM支持獨立的列映射,它允許開發者在模型中定義與映射表列名稱不相同的字段名,Phalcon會識別新的字段名稱,并重命名字段以匹配數據庫中相應的列。這是一項很棒的功能,當需要重命名數據庫中的列名稱時,不需要更改查詢代碼,模型中的映射列會處理好這一切。例如:
"code", "the_name" => "theName", "the_type" => "theType", "the_year" => "theYear", ]; } }然后,可以使用新的字段名:
theName, " "; // 根據type排序 $robot = Robots::find( [ "order" => "theType DESC", ] ); foreach ($robots as $robot) { echo "Code: ", $robot->code, " "; } // 添加記錄 $robot = new Robots(); $robot->code = "10101"; $robot->theName = "Bender"; $robot->theType = "Industrial"; $robot->theYear = 2999; $robot->save();重命名字段時需要注意以下事項:
關系 / 驗證器中對屬性的引用必須使用新名稱
引用實際列名稱將導致ORM異常
獨立列映射允許:
使用自定義約定編寫應用程序
清除代碼中列的前后綴
改變列名稱時,無需更改應用代碼
記錄快照(Record Snapshots)查詢時可以設置特定的模型以保持記錄快照。可以使用此功能來實現審計,或是根據持久性查詢的數據了解哪些字段發生了改變:
keepSnapshots(true); } }當激活此功能時,應用程序會消耗更多的內存來與持久性查詢的原始數據保持同步。在激活此功能的模型中,可以按如下方式檢查發生改變的字段:
name = "Other name"; var_dump($robot->getChangedFields()); // ["name"] var_dump($robot->hasChanged("name")); // true var_dump($robot->hasChanged("type")); // false快照會在模型創建 / 更新時自動更新,使用hasUpdated()方法和getUploadedFields()方法檢查create / save / update操作后,字段是否更新。但是在afterUpdate(),afterSave()和afterCreate()方法中調用getChangedFields()方法,會導致應用程序出問題。
可以禁用此功能:
false, ] );也可以在php.ini中設置:
phalcon.orm.update_snapshot_on_save = 0使用此功能會產生以下效果:
keepSnapshots(true); } } $user = new User(); $user->name = "Test User"; $user->create(); var_dump($user->getChangedFields()); $user->login = "testuser"; var_dump($user->getChangedFields()); $user->update(); var_dump($user->getChangedFields());在Phalcon 3.1.0及之后的版本中:
array(0) { } array(1) { [0] => string(5) "login" } array(0) { }getUpdatedFields()方法將正確返回更新的字段,或如上所述,可以通過設置相關的ini值回到先前的行為。
指向不同模式(Pointing to a different schema)如果模型映射到非默認的模式 / 數據庫,可以使用setSchema()方法重新定義它:
setSchema("toys"); } }多數據庫配置(Setting multiple databases)Phalcon應用中,所有模型可以屬于相同的數據庫連接,或具有獨立的數據庫連接。實際上,當PhalconMvcModel需要連接數據庫時,它會在應用程序的服務容器中請求數據庫服務。可以在initialize()方法中設置,覆蓋該服務:
set( "dbMysql", function () { return new MysqlPdo( [ "host" => "localhost", "username" => "root", "password" => "secret", "dbname" => "invo", ] ); } ); // 注冊PostgreSQL數據庫服務 $di->set( "dbPostgres", function () { return new PostgreSQLPdo( [ "host" => "localhost", "username" => "postgres", "password" => "", "dbname" => "invo", ] ); } );然后,在initialize()方法中為模型定義連接服務:
setConnectionService("dbPostgres"); } }Phalcon提供了更靈活的操作,可以定義只讀連接或寫連接,這對于負載均衡和主從架構的的數據庫非常有用:
setReadConnectionService("dbSlave"); $this->setWriteConnectionService("dbMaster"); } }ORM還支持分片功能,允許根據當前查詢條件實施分片選擇:
0 && $id < 10000) { return $this->getDI()->get("dbShard1"); } if ($id > 10000) { return $this->getDI()->get("dbShard2"); } } } // 使用默認分片 return $this->getDI()->get("dbShard0"); } }selectReadConnection()方法選擇合適的連接,會影響任何新執行的查詢:
注入服務到模型(Injecting services into Models)有時可能需要在模型中訪問應用程序服務,以下示例介紹了如何執行此操作:
getDI()->getFlash(); $messages = $this->getMessages(); // 顯示驗證消息 foreach ($messages as $message) { $flash->error($message); } } }創建或更新操作執行失敗時會觸發notSaved事件,因此我們從DI容器中獲取flash服務,然后閃存驗證消息。這樣,我們不必在每次保存后打印消息。
禁用 / 啟用功能(Disabling / Enabling Features)在ORM中,我們實現了一種機制,允許在全局范圍內啟用 / 禁用特定功能或選項,根據ORM的使用情況,可以禁用那些你沒有使用到的功能。如有需要,下面這些選項可以暫時禁用:
false, "columnRenaming" => false, ] );可用選項:
選項 | 說明 | 默認值 |
---|---|---|
astCache | 啟用 / 禁用模型中的回調、鉤子和事件通知 | null |
cacheLevel | 設置ORM的緩存級別 | 3 |
castOnHydrate | false | |
columnRenaming | 啟用 / 禁用字段重命名 | true |
disableAssignSetters | 模型中禁用setter | false |
enableImplicitJoins | true | |
enableLiterals | true | |
escapeIdentifiers | true | |
events | 啟用 / 禁用模型中的回調、鉤子和事件通知 | true |
exceptionOnFailedSave | 啟用 / 禁用save()操作失敗時拋出異常 | false |
forceCasting | false | |
ignoreUnknownColumns | 啟用 / 禁用忽略模型上的未知字段 | false |
lateStateBinding | 啟用 / 禁用PhalconMvcModel::cloneResultMap()方法的延遲綁定 | false |
notNullValidations | ORM自動驗證映射表中的非空列 | true |
parserCache | null | |
phqlLiterals | 啟用 / 禁用PHQL解析器中的字面量 | true |
uniqueCacheId | 3 | |
updateSnapshotOnSave | 啟用 / 禁用save()方法的更新快照 | true |
virtualForeignKeys | 啟用 / 禁用虛擬外鍵 | true |
注意,給PhalconMvcModel::assign()方法(創建 / 更新 / 保存模型中常用到它)傳遞參數時,setters始終會被調用,這會給應用程序增加額外開銷。可以在php.ini文件中添加配置phalcon.orm.disable_assign_setters = 1,這樣就只會簡單的使用$this->property = value。
獨立組件(Stand-Along component)下面演示以獨立組件模式使用PhalconMvcModel:
set( "db", new Connection( [ "dbname" => "sample.db", ] ) ); // 創建模型管理器 $di->set( "modelsManager", new ModelsManager() ); // 使用內存元數據適配器或其他 $di->set( "modelsMetadata", new MetaData() ); // 創建模型 class Robots extends Model { } // 使用模型 echo Robots::count();
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28682.html
摘要:原文發表于入門教程之模型提供了四種方式操作數據庫模型數據庫抽象層以及原生。創建模型模型類的命名必須符合駝峰命名法,而且須繼承自類文件路徑繼承自類。 原文發表于:Phalcon入門教程之模型 Phalcon 提供了四種方式操作Mysql數據庫:模型、PHQL、數據庫抽象層以及原生SQL。不論何種方式,首先都需要在DI中注冊 db 服務才能正常使用: DI注冊db服務 // 文件路徑:...
摘要:本文描述了框架中數據庫操作方法,主要討論框架的組件中的操作方法。屬性方法在框架中支持屬性的擴展查詢,在上例中,可以把條件語句改為同時省略查詢條件結果不變。 本文描述了PHP-Phalcon框架中數據庫操作方法,主要討論Phalcon框架的Model組件中的操作方法。更詳細的Model介紹請參考:官方文檔 1. 連接數據庫 在Phalcon框架中,通過在DI中注入db參數來實現數據庫的...
摘要:查詢語言查詢語言,簡稱或,是一種面向對象的高級語言,允許用標準化的編寫。該對象的每個成員都是一個包含所查詢字段的標準對象。 Phalcon查詢語言(Phalcon Query Language) Phalcon查詢語言,簡稱PhalconQL或PHQL,是一種面向對象的高級SQL語言,允許用標準化的SQL編寫。PHQL實現了把操作語句解析為RDBMS目標語言的解析器(C語言編寫)。 為...
摘要:原文發表于入門教程之目錄結構很多初學的朋友,對于以框架為基礎構建的項目,應該如何組織目錄結構有點摸不著頭腦。只需要通過注冊這些目錄結構,即可正常使用。 原文發表于:Phalcon入門教程之目錄結構 很多初學Phalcon的朋友,對于以Phalcon框架為基礎構建的項目,應該如何組織目錄結構有點摸不著頭腦。比如多模塊的項目中,如何共用libs類庫和models目錄中模型類的情況,就有很...
摘要:數據庫抽象層是底層組件,由它驅動框架中的模型層。它完全由語言編寫,是一個獨立的數據庫高級抽象層。使用任何數據庫適配器,數據都會被自動轉義。配合使用,可以在數據庫抽象層上提供日志記錄功能。語法因數據庫而異。并非所有數據庫系統都允許修改列或 數據庫抽象層(Database Abstraction Layer) PhalconDb是PhalconMvcModel底層組件,由它驅動框架中的模型...
閱讀 1743·2021-09-22 15:25
閱讀 1307·2019-08-29 12:34
閱讀 1908·2019-08-26 13:57
閱讀 3188·2019-08-26 10:48
閱讀 1443·2019-08-26 10:45
閱讀 793·2019-08-23 18:23
閱讀 733·2019-08-23 18:01
閱讀 1945·2019-08-23 16:07