在開發資料存取層時,若能根據模型物件自動產生 INSERT 語句,將大幅減少重複代碼。本文展示如何使用 PHP 反射(Reflection)讀取模型屬性,動態組裝 SQL 並執行插入,同時支援選擇性回傳自增 ID。
/**
* 利用反射自動插入模型資料
* @param object $model 繼承 BaseModel 的模型實例
* @param bool $is_returnLastInsertId 是否回傳新增的自增 ID
* @return int|bool 成功筆數或最後插入 ID
*/
public function insertModel($model, $is_returnLastInsertId = FALSE) {
try {
require_once dirname(dirname(__FILE__)) . '\Models\BaseModel.php';
if (!is_subclass_of($model, "BaseModel")) {
exit($this->getError(__FUNCTION__, __LINE__));
}
$className = get_class($model);
$tName = $this->formatTabName($className);
$reflectionClass = new ReflectionClass($className);
$properties = $reflectionClass->getProperties();
unset($properties[0]); // 假設第一個屬性為主鍵,略過
$fields = "";
$vals = "";
foreach ($properties as $property) {
$pName = $property->getName();
$fields .= $pName . ",";
$vals .= "'" . $model->$pName . "',";
}
$fields = rtrim($fields, ',');
$vals = rtrim($vals, ',');
$this->sql = "INSERT INTO {$tName} ({$fields}) VALUES ({$vals})";
if ($is_returnLastInsertId) {
$this->conn->exec($this->sql);
$lastId = (int)$this->conn->lastInsertId();
return $lastId;
} else {
$row = $this->conn->exec($this->sql);
return $row;
}
} catch (Exception $exc) {
echo $exc->getMessage();
}
}
ReflectionClass 可在執行時檢視類別結構,取得所有屬性(getProperties())。unset($properties[0]) 跳過第一個屬性(通常為主鍵 ID),避免手動指定自增欄位。lastInsertId(),符合不同業務需求。PDO::prepare() + 參數綁定。