完成Model中的findAll/updateAll/deleteAll/insert/update和delete方法~~
在之前的博客中,我們實現並完善了Model類的findOne方法,下麵我們來實現其中的其他方法。
先來看findAll方法,這個方法和findOne很相似。
public static function findOne($condition = null)
{
$sql = 'select * from ' . static::tableName();
$params = [];
// 判空
if (!empty($condition)) {
$sql .= ' where ';
$params = array_values($condition);
$keys = [];
foreach ($condition as $key => $value) {
array_push($keys, "$key = ?");
}
$sql .= implode(' and ', $keys);
}
$stmt = static::getDb()->prepare($sql);
$rs = $stmt->execute($params);
$models = [];
if ($rs) {
// 直接獲取出所有符合條件的
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
if (!empty($row)) {
$model = new static();
foreach ($row as $rowKey => $rowValue) {
$model->$rowKey = $rowValue;
}
array_push($models, $model);
}
}
}
return null;
}
你會發現有findOne和findAll方法很相似,明顯可以將公共的部分抽出來,然後我們就多瞭如下兩個方法:
/**
* Build a sql where part
* @param mixed $condition a set of column values
* @return string
*/
public static function buildWhere($condition, $params = null)
{
if (is_null($params)) {
$params = [];
}
$where = '';
if (!empty($condition)) {
$where .= ' where ';
$keys = [];
foreach ($condition as $key => $value) {
array_push($keys, "$key = ?");
array_push($params, $value);
}
$where .= implode(' and ', $keys);
}
return [$where, $params];
}
/**
* Convert array to model
* @param mixed $row the row data from database
*/
public static function arr2Model($row)
{
$model = new static();
foreach ($row as $rowKey => $rowValue) {
$model->$rowKey = $rowValue;
}
return $model;
}
分別是構建sql中where部分的方法和將查找到的Array轉換成Model的方法。大家會奇怪第一個方法中為什麼需要params參數和返回值,其實這個為了之後的updateAll方法的使用。其實這個地方跟適合使用引用傳值。
這樣我們的findOne和findAll就便成瞭如下內容:
/**
* Returns a single model instance by a primary key or an array of column values.
*
* ```php
* // find the first customer whose age is 30 and whose status is 1
* $customer = Customer::findOne(['age' => 30, 'status' => 1]);
* ```
*
* @param mixed $condition a set of column values
* @return static|null Model instance matching the condition, or null if nothing matches.
*/
public static function findOne($condition = null)
{
list($where, $params) = static::buildWhere($condition);
$sql = 'select * from ' . static::tableName() . $where;
$stmt = static::getDb()->prepare($sql);
$rs = $stmt->execute($params);
if ($rs) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!empty($row)) {
return static::arr2Model($row);
}
}
return null;
}
/**
* Returns a list of models that match the specified primary key value(s) or a set of column values.
*
* ```php
* // find customers whose age is 30 and whose status is 1
* $customers = Customer::findAll(['age' => 30, 'status' => 1]);
* ```
*
* @param mixed $condition a set of column values
* @return array an array of Model instance, or an empty array if nothing matches.
*/
public static function findAll($condition = null)
{
list($where, $params) = static::buildWhere($condition);
$sql = 'select * from ' . static::tableName() . $where;
$stmt = static::getDb()->prepare($sql);
$rs = $stmt->execute($params);
$models = [];
if ($rs) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as $row) {
if (!empty($row)) {
$model = static::arr2Model($row);
array_push($models, $model);
}
}
}
return $models;
}
剩下的updateAll/deleteAll/insert/update和delete方法就不一一詳細說明瞭,直接給出代碼。其基本思想都是一致的,都是按照規則拼接SQL語句。
/**
* Updates models using the provided attribute values and conditions.
* For example, to change the status to be 2 for all customers whose status is 1:
*
* ~~~
* Customer::updateAll(['status' => 1], ['status' => '2']);
* ~~~
*
* @param array $attributes attribute values (name-value pairs) to be saved for the model.
* @param array $condition the condition that matches the models that should get updated.
* An empty condition will match all models.
* @return integer the number of rows updated
*/
public static function updateAll($condition, $attributes)
{
$sql = 'update ' . static::tableName();
$params = [];
if (!empty($attributes)) {
$sql .= ' set ';
$params = array_values($attributes);
$keys = [];
foreach ($attributes as $key => $value) {
array_push($keys, "$key = ?");
}
$sql .= implode(' , ', $keys);
}
list($where, $params) = static::buildWhere($condition, $params);
$sql .= $where;
$stmt = static::getDb()->prepare($sql);
$execResult = $stmt->execute($params);
if ($execResult) {
// 獲取更新的行數
$execResult = $stmt->rowCount();
}
return $execResult;
}
/**
* Deletes models using the provided conditions.
* WARNING: If you do not specify any condition, this method will delete ALL rows in the table.
*
* For example, to delete all customers whose status is 3:
*
* ~~~
* Customer::deleteAll([status = 3]);
* ~~~
*
* @param array $condition the condition that matches the models that should get deleted.
* An empty condition will match all models.
* @return integer the number of rows deleted
*/
public static function deleteAll($condition)
{
list($where, $params) = static::buildWhere($condition);
$sql = 'delete from ' . static::tableName() . $where;
$stmt = static::getDb()->prepare($sql);
$execResult = $stmt->execute($params);
if ($execResult) {
// 獲取刪除的行數
$execResult = $stmt->rowCount();
}
return $execResult;
}
/**
* Inserts the model into the database using the attribute values of this record.
*
* Usage example:
*
* ```php
* $customer = new Customer;
* $customer->name = $name;
* $customer->email = $email;
* $customer->insert();
* ```
*
* @return boolean whether the model is inserted successfully.
*/
public function insert()
{
$sql = 'insert into ' . static::tableName();
$params = [];
$keys = [];
foreach ($this as $key => $value) {
array_push($keys, $key);
array_push($params, $value);
}
// 構建由?組成的數組,其個數與參數相等數相同
$holders = array_fill(0, count($keys), '?');
$sql .= ' (' . implode(' , ', $keys) . ') values ( ' . implode(' , ', $holders) . ')';
$stmt = static::getDb()->prepare($sql);
$execResult = $stmt->execute($params);
// 將一些自增值賦回Model中
$primaryKeys = static::primaryKey();
foreach ($primaryKeys as $name) {
// Get the primary key
$lastId = static::getDb()->lastInsertId($name);
$this->$name = (int) $lastId;
}
return $execResult;
}
/**
* Saves the changes to this model into the database.
*
* Usage example:
*
* ```php
* $customer = Customer::findOne(['id' => $id]);
* $customer->name = $name;
* $customer->email = $email;
* $customer->update();
* ```
*
* @return integer|boolean the number of rows affected.
* Note that it is possible that the number of rows affected is 0, even though the
* update execution is successful.
*/
public function update()
{
$primaryKeys = static::primaryKey();
$condition = [];
foreach ($primaryKeys as $name) {
$condition[$name] = isset($this->$name) ? $this->$name : null;
}
$attributes = [];
foreach ($this as $key => $value) {
if (!in_array($key, $primaryKeys, true)) {
$attributes[$key] = $value;
}
}
return static::updateAll($condition, $attributes) !== false;
}
/**
* Deletes the model from the database.
*
* @return integer|boolean the number of rows deleted.
* Note that it is possible that the number of rows deleted is 0, even though the deletion execution is successful.
*/
public function delete()
{
$primaryKeys = static::primaryKey();
$condition = [];
foreach ($primaryKeys as $name) {
$condition[$name] = isset($this->$name) ? $this->$name : null;
}
return static::deleteAll($condition) !== false;
}
這樣基本的Model就算是暫時完成了,雖然可能還有很多問題和局限,但暫時先這樣了,我們之後有機會會一步一步的去完善。
好了,今天就先到這裡。項目內容和博客內容也都會放到Github上,歡迎大家提建議。
code:https://github.com/CraryPrimitiveMan/simple-framework/tree/0.7
blog project:https://github.com/CraryPrimitiveMan/create-your-own-php-framework