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; }
public function totalCount() { if ($this->nTotalCount < 0) { $this->nTotalCount = Selecter::singleton()->totalCount(DB::singleton(), $this->prototype(), $this->aLoadRestriction); } return $this->nTotalCount; }
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); }
/** * @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); }
/** * @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; }
public static function translateTableName($sTable, $sAlias, array &$arrToken, array &$arrTokenTree) { return array(DB::singleton()->transTableName($sTable), $sAlias); }
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; }
public function db() { if (!$this->aDB) { $this->aDB = DB::singleton(); } return $this->aDB; }
public function db() { return DB::singleton(); }