//objects = new SplObjectStorage();
let this->dbServiceName = dbServiceName;
}
public function save(var name, <\PhalconPlus\Base\Model> model, array initial_data = [])
{
if !empty initial_data {
model->assign(initial_data);
}
if !model->exists() {
this->insert(name, model, initial_data, false);
} else {
this->update(name, model, initial_data, false);
}
}
public function insert(var name, <\Phalcon\Mvc\Model> model, array initial_data = [], boolean assign = true)
{
if !empty initial_data && assign == true {
model->assign(initial_data);
}
this->detach(model);
this->attach(model, [
"method" : "insert",
"name" : name,
"initial_data" : initial_data
]);
}
public function update(var name, <\Phalcon\Mvc\Model> model, array initial_data = [], boolean assign = true)
{
if !empty initial_data && assign == true {
model->assign(initial_data);
}
this->detach(model);
this->attach(model, [
"method" : "update",
"name" : name,
"initial_data" : initial_data
]);
}
public function delete(var name, <\Phalcon\Mvc\Model> model)
{
this->detach(model);
this->attach(model, [
"method" : "delete",
"name" : name
]);
}
protected function attach(var model, var info)
{
this->objects->attach(model, info);
}
public function detach(model)
{
this->objects->detach(model);
}
public function exec()
{
let this->exception = null;
let this->failed = null;
let this->deleted = new SplObjectStorage();
let this->inserted = new SplObjectStorage();
let this->updated = new SplObjectStorage();
var txManager, transaction, e;
let txManager = new TxManager();
txManager->setDbService(this->dbServiceName);
let transaction = txManager->get();
var obj, info;
this->objects->rewind();
try {
while(this->objects->valid()) {
let obj = this->objects->current();
let info = this->objects->getInfo();
var method, name;
let method = info["method"];
let name = info["name"];
unset(info["method"]); unset(info["name"]);
obj->setTransaction(transaction);
var newMethod;
let newMethod = "exec".ucfirst(method);
if (this->{newMethod}(obj, info) == false) {
transaction->rollback("Model exec failed: " . name . ":" . method);
}
this->objects->next();
}
transaction->commit();
} catch TxFailed, e {
let this->failed = obj;
let this->exception = e;
return false;
}
return true;
}
public function execInsert(<\Phalcon\Mvc\Model> model, array info)
{
var initial_data, result, last_insert_id;
let initial_data = info["initial_data"];
if !empty(initial_data) {
var col, val;
for col, val in initial_data {
if is_callable(val) {
let initial_data[col] = {val}();
}
}
let result = model->create(initial_data);
} else {
let result = model->create();
}
if result == true {
let last_insert_id = model->getWriteConnection()->lastInsertId();
this->inserted->attach(model, [
"last_insert_id" : last_insert_id
]);
}
return result;
}
public function execUpdate(<\Phalcon\Mvc\Model> model, array info = [])
{
var result, initial_data, metaData, columnMap, whiteList, attrField;
let whiteList = [];
// 过滤所有不需要更新(值为NULL)的字段,
// 通过欺骗Model->_doLowUpdate()来达到此目的,要求必须useDynamicUpdate()和keepSnapshot()
let metaData = model->getModelsMetaData();
let columnMap = metaData->getColumnMap(model);
if typeof columnMap == "array" {
for _, attrField in columnMap {
if empty this->{attrField} {
let whiteList[attrField] = null;
}
}
}
model->setSnapshotData(whiteList); // 实际上我们用了columnMap之后的字段作为data
let initial_data = info["initial_data"];
if(!empty(initial_data)) {
var col, val;
for col, val in initial_data {
if is_callable(val) {
let initial_data[col] = {val}();
}
if is_null(val) {
unset(initial_data[col]);
}
}
let result = model->update(initial_data);
} else {
let result = model->update();
}
if result == true {
this->updated->attach(model);
}
return result;
}
public function execDelete(<\Phalcon\Mvc\Model> model, array info = [])
{
var result;
let result = model->delete();
if result == true {
this->deleted->attach(model);
}
return result;
}
public function getObjects()
{
return this->objects;
}
public function getInserted()
{
return this->inserted;
}
public function getUpdated()
{
return this->updated;
}
public function getDeleted()
{
return this->deleted;
}
public function getException()
{
return this->exception;
}
public function getFailed()
{
return this->failed;
}
}