函数在第一次调用时返回字符串,在后续调用时返回一个对象
Posted
技术标签:
【中文标题】函数在第一次调用时返回字符串,在后续调用时返回一个对象【英文标题】:Function returns string on first call, and an object on subsequent calls 【发布时间】:2013-08-23 12:32:11 【问题描述】:我对此有点困惑,所以我希望有人可以为我解释一下。
我有一个函数旨在从我的一张表visit
返回一列Status
。
function someFunction($visitId = null)
$visit = VisitQuery::create()
->select(array('Status'))
->findPk($visitId);
如果我var_dump($visit)
,当第一次调用该函数时,它会输出:
string '1' (length=1)
随后,相同对该函数的调用似乎返回了一个完整的对象:
object(Visit)[30]
protected 'startCopy' => boolean false
protected 'id' => int 362
protected 'job_id' => int 351
protected 'company_id' => int 2
protected 'type_id' => int 1
protected 'visit_date' => string '2013-08-23 00:00:00' (length=19)
protected 'status' => string '1' (length=1)
...
我是第一次调用该函数,并通过已发布的表单传递了 (int) $visitId
:
var_dump($visitId); // int 362
随后的调用是使用从另一个函数返回的(int) $visitId
进行的,saveVisit()
(它使用 Propel 来保存记录 - 我相信这可能与它有关)。
$visitId = saveVisit($visitId);
var_dump($visitId); // int 362
我尝试进行一些调试,但由于某种原因,第一次函数调用和后续函数调用向 mysql 发出的查询不同:
var_dump($con->getLastExecutedQuery());
SELECT visit.STATUS AS "Status" FROM `visit` WHERE visit.ID=362 // 1st call
SELECT `ID`, `JOB_ID`, `COMPANY_ID`, `TYPE_ID`, `VISIT_DATE`, `STATUS`, `REMIND`, `PRINTED` FROM `visit` WHERE `ID` = 362 // 2nd call
SELECT `ID`, `JOB_ID`, `COMPANY_ID`, `TYPE_ID`, `VISIT_DATE`, `STATUS`, `REMIND`, `PRINTED` FROM `visit` WHERE `ID` = 362 // 3rd call
谁能告诉我这是为什么或如何发生的?
我正在使用 Propel 1.6。
Propel 的create()
方法:
public static function create($modelAlias = null, $criteria = null)
if ($criteria instanceof VisitQuery)
return $criteria;
$query = new VisitQuery();
if (null !== $modelAlias)
$query->setModelAlias($modelAlias);
if ($criteria instanceof Criteria)
$query->mergeWith($criteria);
return $query;
Propel 的findPk()
方法:
public function findPk($key, $con = null)
if ($con === null)
$con = Propel::getConnection($this->getDbName(), Propel::CONNECTION_READ);
// As the query uses a PK condition, no limit(1) is necessary.
$this->basePreSelect($con);
$criteria = $this->isKeepQuery() ? clone $this : $this;
$pkCols = $this->getTableMap()->getPrimaryKeyColumns();
if (count($pkCols) == 1)
// simple primary key
$pkCol = $pkCols[0];
$criteria->add($pkCol->getFullyQualifiedName(), $key);
else
// composite primary key
foreach ($pkCols as $pkCol)
$keyPart = array_shift($key);
$criteria->add($pkCol->getFullyQualifiedName(), $keyPart);
$stmt = $criteria->doSelect($con);
return $criteria->getFormatter()->init($criteria)->formatOne($stmt);
我的访问状态检索函数:
function getVisitStatus($visitId = null)
if (empty($visitId))
return false;
try
$visit = VisitQuery::create()
->select(array('Status'))
->findPk($visitId);
catch (Exception $e)
echo $e->getMessage(); exit;
if (is_null($visit))
return false;
return $visit;
保存访问记录的功能:
function saveVisit($data = null)
if (empty($data))
return false;
try
$visit = (!empty($data['visit_id'])) ? VisitQuery::create()->findPk($data['visit_id']) : new Visit();
if (!is_object($visit))
return false;
$visitDataMap = array(
'JobId' => 'job_id',
'TypeId' => 'type_id',
'VisitDate' => 'visit_date',
'Status' => 'status',
'CompanyId' => 'engineer_id',
'Remind' => 'remind'
);
$visitData = array();
foreach ($visitDataMap as $column => $value)
if (!empty($data[$value]))
$visitData[$column] = $data[$value];
$visit->fromArray($visitData);
$visit->save();
return $visit->getId();
catch (PropelException $e)
echo $e->getMessage(); exit;
【问题讨论】:
我会说问题出在VisitQuery::create()
。你能显示create
函数的代码吗?
看起来它第一次会创建一个新的访问并返回1
并且对于每个后续请求它都会返回它之前创建的那个对象,你能发布那个函数的完整代码
@ØHankyPankyØ 我已经在问题中添加了完整的功能
好的,现在可以请您粘贴这些方法的代码:findPk
和VisitQuery::create
@ØHankyPankyØ 我已经发布了所有相关代码
【参考方案1】:
似乎在第一次调用时会获取您的数据,然后将完整对象的副本放入实例池中。我不确定这是错误还是有效行为(您的代码会建议使用前者,但我很想听听更了解 Propel 的人,例如开发人员),但您可以通过以下方式阻止它发生:
VisitPeer::clearInstancePool();
请记住,您可能在此处使用 visit
关系完成的其他查询丢失了一些缓存。
您可以通过在BaseVisitPeer.php
文件中添加回显来确认这一点。你会看到这样的东西:
public static function getInstanceFromPool($key)
if (Propel::isInstancePoolingEnabled())
if (isset(VisitPeer::$instances[$key]))
return VisitPeer::$instances[$key];
return null; // just to be explicit
如果您在 if (isset(VisitPeer::$instances[$key]))
语句中的某处添加回显,您应该会看到它仅在第二次和后续调用之后出现。如果您要将整个 if 语句注释掉,那么您每次都会得到相同的结果 - 您从原始调用中正确返回的结果。
希望有帮助!
【讨论】:
以上是关于函数在第一次调用时返回字符串,在后续调用时返回一个对象的主要内容,如果未能解决你的问题,请参考以下文章