Esempio n. 1
0
 protected function deleteBridge(DB $aDB, Association $aAssociation, Model $aFromModel, Model $aToModel)
 {
     $aStatementFactory = $aAssociation->fromPrototype()->statementFactory();
     $aDeleteForBridge = $aStatementFactory->createDelete($aAssociation->bridgeTableName());
     $aDeleteForBridge->criteria()->where()->add($this->makeRestrictionForAssocotion($aFromModel, $aAssociation->fromKeys(), null, $aAssociation->toBridgeKeys(), $aStatementFactory));
     $aDB->execute($aDeleteForBridge);
 }
Esempio n. 2
0
 public static function reflectTableIndexes($sTableName, $sDBName = null, DB $aDB = null)
 {
     if (!$aDB) {
         $aDB = DB::singleton();
     }
     if (!($aResult = $aDB->query(self::makeIndexSql($sTableName, $sDBName))) or $aResult->rowCount() == 0) {
         return array();
     }
     $arrAllIndexes = array();
     foreach ($aResult->fetchAll(\PDO::FETCH_ASSOC) as $arrIndexRow) {
         if (!isset($arrAllIndexes[$arrIndexRow['Key_name']])) {
             $arrAllIndexes[$arrIndexRow['Key_name']] = $arrIndexRow;
         }
         $arrAllIndexes[$arrIndexRow['Key_name']]['columns'][] = $arrIndexRow['Column_name'];
     }
     $arrIndexReflecters = array();
     foreach ($arrAllIndexes as $sIndexName => $arrIndex) {
         $aIndexReflecter = new self();
         // $aIndexReflecter
         $aIndexReflecter->bIsPrimary = $arrIndex['Key_name'] == 'PRIMARY';
         $aIndexReflecter->bIsFullText = $arrIndex['Index_type'] == 'FULLTEXT';
         $aIndexReflecter->bIsUnique = $arrIndex['Non_unique'] == '0';
         $aIndexReflecter->sName = $sIndexName;
         $aIndexReflecter->arrColumnsNames = $arrIndex['columns'];
         $arrIndexReflecters[$sIndexName] = $aIndexReflecter;
     }
     return $arrIndexReflecters;
 }
Esempio n. 3
0
 public function totalCount()
 {
     if ($this->nTotalCount < 0) {
         $this->nTotalCount = Selecter::singleton()->totalCount(DB::singleton(), $this->prototype(), $this->aLoadRestriction);
     }
     return $this->nTotalCount;
 }
Esempio n. 4
0
 private function moveCategory(Update $aUpdate, $nMove, $gtLft, $ltRgt, $sLftClm, $sRgtClm)
 {
     $aCriateria = $aUpdate->criteria();
     $aCriateria->where()->clear();
     if ($gtLft !== null) {
         $aCriateria->where()->gt('lft', $gtLft);
     }
     if ($ltRgt !== null) {
         $aCriateria->where()->lt('rgt', $ltRgt);
     }
     $aUpdate->clearData();
     $aUpdate->setData('lft', "{$sLftClm}+{$nMove}", true);
     $aUpdate->setData('rgt', "{$sRgtClm}+{$nMove}", true);
     DB::singleton()->execute($aUpdate);
 }
Esempio n. 5
0
 protected function buildBridge(DB $aDB, Association $aAssociation, Model $aFromModel, Model $aToModel)
 {
     $aFromPrototype = $aAssociation->fromPrototype();
     $aSelect = new Select($aAssociation->bridgeTableName());
     $aRestraction = $aSelect->criteria()->where();
     $this->makeResrictionForAsscotion($aRestraction, $aFromPrototype->path(), $aAssociation->fromKeys(), null, $aAssociation->toBridgeKeys());
     $this->makeResrictionForAsscotion($aRestraction, $aAssociation->toPrototype()->path(), $aAssociation->toKeys(), null, $aAssociation->fromBridgeKeys());
     // 检查对应的桥接表记录是否存在
     if (!$aDB->queryCount($aSelect)) {
         $aInsertForBridge = $aStatementFactory->createInsert($aAssociation->bridgeTableName());
         // from table key vale
         $this->setValue($aInsertForBridge, $aAssociation->toBridgeKeys(), $aAssociation->fromKeys(), $aFromModel);
         // to table key vale
         $this->setValue($aInsertForBridge, $aAssociation->fromBridgeKeys(), $aAssociation->toKeys(), $aToModel);
         $aDB->execute($aInsertForBridge);
     }
 }
Esempio n. 6
0
 /**
  * @wiki /MVC模式/控制器/请求-回应(request-response)
  * 
  * ===控制器 请求===
  * TODO ...
  * 
  * ===控制器 响应===
  * 控制器的执行结果如何提供给控制器的客户((^)控制器的客户(client)既可以是系统,也可以是用户),由[b]响应(Response)[/b]对像负责。
  * 
  * 在目前框架的设计中,控制器主要有三种”内容“可供输出:
  * * 控制器的消息队列
  * * 控制器的视图
  * * 控制器“放置”到[b]响应(Response)[/b]对像中的变量
  * 由[b]响应(Response)[/b]对像来决定向什么设备输出这些内容输出哪些内容。
  * 
  * [^]\
  * 在默认情况下,控制器会向系统提供一个 org\jecat\framework\mvc\controller\Response 对像做为[b]响应[/b]对像,它会将默认的输出管道做为控制器的输出设备;\
  * 并根据使用[b]请求(Request)[/b]对像中的参数决定输出策略。
  * 你也可以给控制器设置完全不同的[b]响应[/b]对像。\
  * [/^]
  * 
  * 
  * Controller类默认提供的Response对像,会根据[b]请求(Request)[/b]对像中的一些特殊参数来输出控制器的执行结果:
  * 
  * 
  * =参数 rspn=
  * rspn 参数指定了控制器向[b]响应(response)[/b]对像的输出管道,以何种形式输出何种内容。rspn参数可以是以下值:
  * * rspn=[b]msgqueue.json[/b]
  * 以json格式输出控制器消息队列中的内容
  * * rspn=[b]msgqueue.xml[/b]
  * 以xml格式输出控制器消息队列中的内容
  * * rspn=[b]msgqueue.html[/b]
  * 以html格式输出控制器消息队列中的内容
  * * rspn=[b]msgqueue[/b]
  * (和 msgqueue.html 相同)
  * * rspn=[b]var.php[/b]
  * 以php语法格式输出控制器执行后的所有结果变量					
  * * rspn=[b]var.xml[/b]
  * 以xml格式输出控制器执行后的所有结果变量
  * * rspn=[b]var.json[/b]			
  * 以json格式输出控制器执行后的所有结果变量
  * * rspn=[b]var[/b]
  * (和 var.json 相同)
  * * rspn=[b]view.noframe[/b]			
  * 禁止显示控制器 frame 部分的视图
  * * rspn=[b]noframe[/b]			
  * (和 view.noframe 相同)
  * * rspn=[b]view.inframe (默认)[/b]			
  * 在 控制器提供的frame的视图 中显示控制器的视图,这是 rspn参数的缺省值
  * * rspn=[b]inframe[/b]			
  * (和 view.inframe 相同)
  * * rspn=[b]view (默认)[/b]			
  * (和 view.inframe 相同)
  * * rspn=[b]disable[/b]			
  * 禁止输出任何内容(但不会禁止 rspn.debug.* 相关的内容)
  * 
  * [^]如果控制器中没有视图(或视图都被禁用),在 view.* 模式下,系统会输出控制器的消息队列[/^]
  * 
  * 
  * ==调式相关参数==
  * 还有一些用于调式的响应(Response)参数。
  * 
  * =参数 rspn.debug.db.log=
  * 打印整个系统在执行过程中,数据库执行SQL的情况;只要提供这个参数,等于任何值都有效。
  * 
  * =参数 rspn.debug.model.struct=
  * 打印控制器的模型结构和数据内容。
  * 该参数可以是一个表示指定模型的名称的字符串,或表示所有模型的”星号“(*)
  * 
  */
 public function respond(Controller $aController)
 {
     $aEventManager = EventManager::singleton();
     // 触发事件
     $arrEventArgvs = array($this, $aController);
     $aEventManager->emitEvent(__CLASS__, self::beforeRespond, $arrEventArgvs);
     switch ($aController->params()->get('rspn')) {
         // msgqueue ------------
         case 'msgqueue.json':
             break;
         case 'msgqueue.xml':
             break;
         case 'msgqueue':
         case 'msgqueue.html':
             $aController->messageQueue()->display(null, $this->device());
             break;
             // var ------------
         // var ------------
         case 'var':
         case 'var.json':
             $this->device()->write(json_encode($this->arrReturnVariables));
             break;
         case 'var.xml':
             break;
         case 'var.php':
             $this->device()->write(var_export($this->arrReturnVariables, true));
             break;
             // view ------------
         // view ------------
         default:
         case 'view':
         case 'view.inframe':
             if ($aFrame = $aController->frame()) {
                 $aMainView = $aFrame->mainView();
             }
             // 没有 break ,进入下面的 case
         // 没有 break ,进入下面的 case
         case 'noframe':
         case 'view.noframe':
             if (empty($aMainView)) {
                 $aMainView = $aController->mainView();
             }
             // 控制器没有有效视图
             $nValidViews = 0;
             foreach ($aController->viewIterator() as $aView) {
                 if ($aView->isEnable()) {
                     $nValidViews++;
                 }
             }
             if (!$nValidViews) {
                 // 临时提供一个仅显示消息队列的视图
                 $aTmpView = new View('tmp_view_for_msgqueue');
                 $aController->addView($aTmpView);
                 $aController->messageQueue()->display(null, $this->device());
             }
             // 装配视图
             ViewAssembler::singleton()->assemble($aController);
             // 显示视图
             $aOutput = new OutputStreamBuffer();
             $aMainView->render($aOutput);
             $this->device()->write($aOutput);
             // 触发事件
             $arrEventArgvs2 = array($this, $aMainView, $aController);
             $aEventManager->emitEvent(__CLASS__, self::afterRenderViews, $arrEventArgvs2);
             break;
         case 'disable':
             // nothing todo
             break;
     }
     // 打印数据库的执行日志
     if ($aController->params()->has('rspn.debug.db.log')) {
         $this->device()->write('<hr /><h3>数据库执行记录:</h3>');
         // 按执行时间排序
         $arrLogs = DB::singleton()->executeLog(false);
         foreach ($arrLogs as $nIdx => &$arrOneLog) {
             $arrOneLog['idx'] = $nIdx;
         }
         usort($arrLogs, function ($a, $b) {
             if ($a['time'] == $b['time']) {
                 return 0;
             }
             return $a['time'] < $b['time'] ? -1 : 1;
         });
         $fTotal = 0;
         foreach ($arrLogs as $arrLog) {
             $fTotal += $arrLog['time'];
             $this->device()->write("<div style='padding-top:10px'>[{$arrLog['idx']}]=>耗时:{$arrLog['time']} <pre>{$arrLog['sql']}</pre></div>");
         }
         $this->device()->write("\r\n<br />DB共执行了 " . count($arrLogs) . " 条SQL,总计时间:{$fTotal}\r\n<hr />");
     }
     // 打印模型结构
     if ($aController->params()->has('rspn.debug.model.struct')) {
         $sModelName = $aController->params()->get('rspn.debug.model.struct');
         $arrModelNames = array();
         if ($sModelName == '*') {
             // 控制器自己的模型
             foreach ($aController->modelNameIterator() as $sModelName) {
                 $this->device()->write('<hr /><h3>控制器' . $aController->name() . '的模型数据结构:</h3>');
                 $this->printDebugModelStruct($aController, $sModelName);
             }
             // 子控制器的模型
             foreach ($aController->iterator() as $aChildController) {
                 $this->device()->write('<hr /><h3>控制器' . $aChildController->name() . '的模型数据结构:</h3>');
                 foreach ($aChildController->modelNameIterator() as $sModelName) {
                     $this->printDebugModelStruct($aChildController, $sModelName);
                 }
             }
         } else {
             $this->device()->write('<hr /><h3>控制器' . $aController->name() . '的模型数据结构:</h3>');
             $this->printDebugModelStruct($aController, $sModelName);
         }
     }
     // 触发事件
     $aEventManager->emitEvent(__CLASS__, self::afterRespond, $arrEventArgvs);
 }
Esempio n. 7
0
 /**
  * @wiki /MVC模式/数据库模型/数据表关联
  * ==Bean配置数组==
  * type string 指定关系类型
  * fromkeys array 起始表列名
  * tokeys array 目标表列名
  * frombridgekeys array 起始桥接表列名
  * tobridgekeys array 起始桥接表列名
  * bridge string 桥接表名
  * fromPrototype string 指定起源原型配置
  * on string 
  */
 public function buildBean(array &$arrConfig, $sNamespace = '*', \org\jecat\framework\bean\BeanFactory $aBeanFactory = null)
 {
     if (!$this->aDB) {
         $this->aDB = DB::singleton();
     }
     $arrConfigForToPrototype = $arrConfig;
     $arrConfigForToPrototype['class'] = 'prototype';
     $this->aToPrototype = BeanFactory::singleton()->createBean($arrConfigForToPrototype, $sNamespace);
     $this->aToPrototype->setassociatedBy($this);
     if (!empty($arrConfig['type'])) {
         $this->nType = $arrConfig['type'];
     }
     if (!empty($arrConfig['fromkeys'])) {
         $this->setFromKeys($arrConfig['fromkeys']);
     }
     if (!empty($arrConfig['tokeys'])) {
         $this->setToKeys($arrConfig['tokeys']);
     }
     if (!empty($arrConfig['tobridgekeys'])) {
         $this->setToBridgeKeys($arrConfig['tobridgekeys']);
     }
     if (!empty($arrConfig['frombridgekeys'])) {
         $this->setFromBridgeKeys($arrConfig['frombridgekeys']);
     }
     if (!empty($arrConfig['bridge'])) {
         $this->sBridgeTable = $arrConfig['bridge'];
     }
     if (!empty($arrConfig['fromPrototype'])) {
         $this->aFromPrototype = $arrConfig['fromPrototype'];
     }
     if (!empty($arrConfig['on'])) {
         if (is_array($arrConfig['on'])) {
             $arrOnFactors = $arrConfig['on'];
             $this->arrOnRawSql['expr_type'] = 'clause_on';
             $this->arrOnRawSql['subtree'] =& SQL::parseSql(array_shift($arrOnFactors), 'on', true);
             $aOnClause = new SQL($this->arrOnRawSql);
             $aOnClause->addFactors($arrOnFactors);
         } else {
             $this->arrOnRawSql['expr_type'] = 'clause_on';
             $this->arrOnRawSql['subtree'] =& SQL::parseSql($arrConfig['on'], 'on', true);
         }
     }
     if (!empty($arrConfig['join'])) {
         $this->sJoinType = strtoupper($arrConfig['join']);
     }
     $this->done();
     $this->arrBeanConfig = $arrConfig;
 }
Esempio n. 8
0
 private function generateNumValue(DB $aDB, $sTable, $sColumn, $nMinVal)
 {
     $arrRow = $aDB->query("select max(`{$sColumn}`) as maxval from `{$sTable}` ;")->fetch(\PDO::FETCH_ASSOC);
     $maxVal = (int) $arrRow['maxval'];
     return $maxVal < (int) $nMinVal ? $nMinVal : $maxVal + 1;
 }
Esempio n. 9
0
 public static function translateTableName($sTable, $sAlias, array &$arrToken, array &$arrTokenTree)
 {
     return array(DB::singleton()->transTableName($sTable), $sAlias);
 }
Esempio n. 10
0
 public function hasExists(Model $aModel, Prototype $aPrototype = null, Select $aSelect = null, DB $aDB = null)
 {
     if (!$aPrototype) {
         $aPrototype = $aModel->prototype();
     }
     if (!$aSelect) {
         $aSelect = $aPrototype->sharedStatementSelect();
     }
     if (!$aDB) {
         $aDB = DB::singleton();
     }
     // 备份原来的 limit
     $arrRawOriLimit =& $aSelect->rawClause(SQL::CLAUSE_LIMIT, false);
     $aSelect->criteria()->setLimit(1, 0);
     $aRestriction = $aSelect->where()->createRestriction();
     foreach ($aPrototype->keys() as $nIdx => $sKey) {
         $aRestriction->expression(array(SQL::createRawColumn($aPrototype->sqlTableAlias(), $sKey), '=', SQL::transValue($aModel->data($sKey))), true, true);
     }
     // 查询
     $bExists = $aDB->queryCount($aSelect) > 0;
     // 移除条件
     $aSelect->where()->remove($aRestriction);
     // 还原原来的 limit
     $aSelect->setRawClause(SQL::CLAUSE_LIMIT, $arrRawOriLimit);
     return $bExists;
 }
Esempio n. 11
0
 public function db()
 {
     if (!$this->aDB) {
         $this->aDB = DB::singleton();
     }
     return $this->aDB;
 }
Esempio n. 12
0
 public function execute(DB $aDB, Model $aModel)
 {
     $aPrototype = $aModel->prototype();
     $aUpdate = $aPrototype->sharedStatementUpdate();
     // 从 belongs to model 中设置外键值
     foreach ($aPrototype->associations() as $aAssociation) {
         if ($aAssociation->isType(Association::belongsTo)) {
             if (!($aAssociatedModel = $aModel->child($aAssociation->name()))) {
                 continue;
             }
             if (!$aAssociatedModel->save()) {
                 return false;
             }
             $this->setAssociatedModelData($aAssociatedModel, $aModel, $aAssociation->toKeys(), $aAssociation->fromKeys());
         }
     }
     // 产生一个criteria并设置给$aUpdate
     //$aCriteria = StatementFactory::singleton()->createCriteria() ;
     //$aUpdate->setCriteria($aCriteria);
     // 处理主键
     $aUpdate->where()->clear();
     foreach ($aPrototype->keys() as $sKey) {
         //主键发生修改
         if ($aModel->changed($sKey)) {
             throw new ORMException('org\\jecat\\framework\\mvc\\model\\db\\orm\\Updater : Key 有修改,无法进行Update操作');
         } else {
             $aUpdate->where()->expression(array(SQL::createRawColumn(null, $sKey), '=', SQL::transValue($aModel->data($sKey))), true, true);
         }
     }
     $aUpdate->clearData();
     $bFlagChanged = false;
     //当前表是否有修改
     foreach ($aPrototype->columns() as $sClmName) {
         //只update发生修改的项
         if ($aModel->changed($sClmName)) {
             $aUpdate->setData($sClmName, $aModel->data($sClmName), false);
             $bFlagChanged = true;
         }
     }
     //只有当有修改的时候才发生更新
     if ($bFlagChanged) {
         $aDB->execute($aUpdate);
     }
     // update关联model
     foreach ($aPrototype->associations() as $aAssociation) {
         $aAssociatedModel = $aModel->child($aAssociation->name());
         if (!$aAssociatedModel) {
             continue;
         }
         switch ($aAssociation->type()) {
             case Association::hasOne:
                 $this->setAssociatedModelData($aModel, $aAssociatedModel, $aAssociation->fromKeys(), $aAssociation->toKeys());
                 if (!$aAssociatedModel->save()) {
                     return false;
                 }
                 break;
             case Association::belongsTo:
                 // nothing todo ...
                 break;
             case Association::hasMany:
                 $this->setAssociatedModelData($aModel, $aAssociatedModel, $aAssociation->fromKeys(), $aAssociation->toKeys());
                 if (!$aAssociatedModel->save()) {
                     return false;
                 }
                 break;
             case Association::hasAndBelongsToMany:
                 if (!$aAssociatedModel->save()) {
                     return false;
                 }
                 // update bridge table
                 foreach ($aAssociatedModel->childIterator() as $aOneChildModel) {
                     $this->buildBridge($aDB, $aAssociation, $aModel, $aOneChildModel);
                 }
                 break;
         }
     }
     return true;
 }
Esempio n. 13
0
 public function db()
 {
     return DB::singleton();
 }