public function active(&$sToken, ParseState $aParseState) { $arrValuesToken = Insert::createRawInsertValues(); // 追溯前面的 字段列表 if (end($aParseState->arrTree) === ')') { $nDepth = 0; do { $token = array_pop($aParseState->arrTree); if (is_string($token)) { if ($token === ')') { $nDepth++; continue; } else { if ($token === '(') { $nDepth--; continue; } } } if (!empty($token['expr_type']) and $token['expr_type'] === 'column') { $arrValuesToken['pretree']['COLUMNS']['subtree'][$token['column']] = $token; $arrValuesToken['columns'][] = $token['column']; } else { $arrValuesToken['pretree']['COLUMNS']['subtree'][] = $token; } } while ($nDepth); $arrValuesToken['pretree']['COLUMNS']['subtree'] = array_reverse($arrValuesToken['pretree']['COLUMNS']['subtree'], true); if (!empty($arrValuesToken['columns'])) { $arrValuesToken['columns'] = array_reverse($arrValuesToken['columns'], false); } } $aParseState->arrTree[] =& $arrValuesToken; $this->switchToSubTree($aParseState, $arrValuesToken); }
public function execute(DB $aDB, Model $aModel) { $aPrototype = $aModel->prototype(); $aInsert = new Insert($aPrototype->tableName()); // 从 belongs to model 中设置外键值 foreach ($aPrototype->associations() as $aAssociation) { if ($aAssociation->isType(Association::belongsTo)) { if (!($aAssocModel = $aModel->child($aAssociation->name()))) { continue; } if (!$aAssocModel->save()) { return false; } $this->setAssocModelData($aAssocModel, $aModel, $aAssociation->toKeys(), $aAssociation->fromKeys()); } } // ----------------------------------- // insert 当前model $bTableLocked = false; $sTableName = $aPrototype->tableName(); $e = null; try { // 检查/自动生成 主键值 if ($arrKey = $aPrototype->keys()) { foreach ($arrKey as $sKeyName) { if ($aModel->data($sKeyName) === null) { $aClmRef = $aPrototype->columnReflecter($sKeyName); if (!$aClmRef->isAutoIncrement()) { // 锁表 if (!$bTableLocked) { $aDB->execute("LOCK TABLES `{$sTableName}` WRITE ;"); $bTableLocked = true; } // 生成并设置主键值 $keyValue = AutoPrimaryGenerator::singleton()->generate($aClmRef, $sTableName, $aDB); $aModel->setData($sKeyName, $keyValue); } } } } // 设置数据 foreach ($aModel->dataNameIterator() as $sClmName) { $value = $aModel->data($sClmName); if ($value !== null) { $aInsert->setData($sClmName, $value); } } // 执行 insert $aDB->execute($aInsert); } catch (\Exception $e) { } // 解锁后再抛出异常 if ($bTableLocked) { $aDB->execute("UNLOCK TABLES ;"); } if ($e) { throw $e; } // 自增形主键 if ($sDevicePrimaryKey = $aPrototype->devicePrimaryKey() and $aModel->data($sDevicePrimaryKey) === null) { $aModel->setData($sDevicePrimaryKey, $aDB->lastInsertId(), false); } // ----------------------------------- // insert 关联model foreach ($aPrototype->associations() as $aAssociation) { $aAssocModel = $aModel->child($aAssociation->name()); if (!$aAssocModel) { continue; } switch ($aAssociation->type()) { case Association::hasOne: $this->setAssocModelData($aModel, $aAssocModel, $aAssociation->fromKeys(), $aAssociation->toKeys()); if (!$aAssocModel->save()) { return false; } break; case Association::belongsTo: // nothing todo ... break; case Association::hasMany: $this->setAssocModelData($aModel, $aAssocModel, $aAssociation->fromKeys(), $aAssociation->toKeys()); if (!$aAssocModel->save()) { return false; } break; case Association::hasAndBelongsToMany: if (!$aAssocModel->save()) { return false; } // ----------------------- // insert bridge table foreach ($aAssocModel->childIterator() as $aOneChildModel) { $this->buildBridge($aDB, $aAssociation, $aModel, $aOneChildModel); } break; } } return true; }