“无法执行 Model_Hotel::__construct()”使用 mysql_fetch_object,属性保持未初始化状态
我在 Mac OS X Lion 上运行 PHP 5.3.6 和 MAMP 2.0.1,并且使用 Kohana 3.1.3.1。
我尝试用我自己的方法重写标准 Kohana ORM 模块的 __set() 和 __get() 方法。我的一些模型扩展了我的类,从而扩展了 ORM 类。
<?php
class ORM_Localization extends ORM
{
protected static $_language_cache = array();
protected $_languages = array();
public function __construct($id = NULL)
{
parent::__construct($id);
// Load languages which are accepted by the client
$this->_languages = array_keys(Application::languages());
}
public function __get($name)
{
/* Debugging #1 */ echo 'GET'.$name;
/* Debugging #2 */ // exit;
return $this->localization($name);
}
public function __set($name, $value)
{
/* Debugging #3 */ var_dump($this->_table_columns);
/* Debugging #4 */ echo 'SET::'.$name;
/* Debugging #5 */ // exit;
$this->localization($name, $value);
}
public function localization($name, $value = NULL)
{
if (!array_key_exists($name, $this->_table_columns)) {
// Load avaiable languages from database if not already done
if (empty(ORM_Localization::$_language_cache)) {
ORM_Localization::$_language_cache = ORM::factory('languages')
->find_all()
->as_array('id', 'identifier');
}
$languages = array();
// Find the IDs of the languages from the database which match the given language
foreach ($this->languages as $language) {
$parts = explode('-', $language);
do {
$identifier = implode('-', $parts);
if ($id = array_search($identifier, ORM_Localization::$_language_cache)) {
$languages[] = $id;
}
array_pop($parts);
} while($parts);
}
// Find localization
foreach ($languages as $language) {
$localization = $this->localizations->where('language_id', '=', $language)->find();
try {
if ($value === NULL) {
return $localization->$name;
} else {
$localization->$name = $value;
}
} catch (Kohana_Exception $exception) {}
}
}
if ($value === NULL) {
return parent::__get($name);
} else {
parent::__set($name, $value);
}
}
}
但在 PHP 5.3.6 中,我收到以下错误消息:
异常 [0]:无法执行 Model_Hotel::__construct()
Model_Hotel 扩展了此类,并且没有自己的构造。 这是 Model_Hotel 的代码,一个标准的 Kohana ORM 模型: http://pastie.org/private/vuyig90phwqr9f34crwg
使用 PHP 5.2.17,我得到了另一个:
ErrorException [警告]:array_key_exists() [function.array-key-exists]:第二个参数应该是数组或对象
在Kohana中,扩展我的类的模型由mysql_fetch_object()调用,位于orm深处的某个地方模块代码。
但是,如果我在 __set() 中回显被调用的属性并随后退出(#4 和 #5),它会输出“SET::id”并且不会显示错误消息。
如果我 var_dump() $this->_table_columns (或此类的任何其他属性,#3),我会得到“NULL”,这是该属性在初始化之前的值。 如果我对 $this->_languages 重复相同的操作,我会得到一个空数组,该数组应该填充多种语言。就好像该类从未使用 __construct 进行初始化。这解释了我在 PHP 5.2.17 中遇到的错误,因为 $this->_table_columns 是 NULL 而不是数组。
我可以取消注释我的 __construct,但仍然遇到相同的错误,错误必须出在我的 localization() 方法中。
我已经搜索了好几天了,我完全不知道可能出了什么问题。
I'm running PHP 5.3.6 with MAMP 2.0.1 on Mac OS X Lion and I'm using Kohana 3.1.3.1.
I try to override the __set() and __get() methods of the standard Kohana ORM module with my own methods. Some of my models extend my class which extends the ORM class.
<?php
class ORM_Localization extends ORM
{
protected static $_language_cache = array();
protected $_languages = array();
public function __construct($id = NULL)
{
parent::__construct($id);
// Load languages which are accepted by the client
$this->_languages = array_keys(Application::languages());
}
public function __get($name)
{
/* Debugging #1 */ echo 'GET'.$name;
/* Debugging #2 */ // exit;
return $this->localization($name);
}
public function __set($name, $value)
{
/* Debugging #3 */ var_dump($this->_table_columns);
/* Debugging #4 */ echo 'SET::'.$name;
/* Debugging #5 */ // exit;
$this->localization($name, $value);
}
public function localization($name, $value = NULL)
{
if (!array_key_exists($name, $this->_table_columns)) {
// Load avaiable languages from database if not already done
if (empty(ORM_Localization::$_language_cache)) {
ORM_Localization::$_language_cache = ORM::factory('languages')
->find_all()
->as_array('id', 'identifier');
}
$languages = array();
// Find the IDs of the languages from the database which match the given language
foreach ($this->languages as $language) {
$parts = explode('-', $language);
do {
$identifier = implode('-', $parts);
if ($id = array_search($identifier, ORM_Localization::$_language_cache)) {
$languages[] = $id;
}
array_pop($parts);
} while($parts);
}
// Find localization
foreach ($languages as $language) {
$localization = $this->localizations->where('language_id', '=', $language)->find();
try {
if ($value === NULL) {
return $localization->$name;
} else {
$localization->$name = $value;
}
} catch (Kohana_Exception $exception) {}
}
}
if ($value === NULL) {
return parent::__get($name);
} else {
parent::__set($name, $value);
}
}
}
But in PHP 5.3.6, I get the following error message:
Exception [ 0 ]: Could not execute Model_Hotel::__construct()
Model_Hotel extends this class and does not have an own construct.
This is the code of Model_Hotel, a standard Kohana ORM model: http://pastie.org/private/vuyig90phwqr9f34crwg
With PHP 5.2.17, I get another one:
ErrorException [ Warning ]: array_key_exists() [function.array-key-exists]: The second argument should be either an array or an object
In Kohana, my model which extends my class is called by mysql_fetch_object(), somewhere deep in the orm modules code.
However, if I echo the called property in __set() and exit (#4 and #5) afterwards, it outputs "SET::id" and doesn't show the error message.
If I var_dump() $this->_table_columns (or any other property of this class, #3), I get "NULL" which is the value that this property has before it's initialized.
If I repeat the same with $this->_languages, I get an empty array which should be filled with several languages. It's like the class was never initialized with the __construct. This explains the error which I get in PHP 5.2.17, because $this->_table_columns is NULL and not an array.
I can uncomment my __construct and I still get the same error, the fault has to be in my localization() method.
I searched for several days now and I have absolutely no idea what could be wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
ORM::__set()
预计会从mysql_fetch_object()
调用加载转换数据。为此,您必须允许它设置强制转换值:虽然我也不喜欢这个解决方案,但您应该重写
ORM::set()
。ORM::__set()
is expected to load cast data frommysql_fetch_object()
call. You must allow it to set casted value for this cause:Altough I don't like this solution either, you should be overriding
ORM::set()
instead.__construct()
在对象初始化后自动调用。__construct()
is called automatically after initialization of an object.我对这个问题有更多的信息,因为我遇到了同样的问题。
1)我发现一个 PHP 错误报告,其中记录了在 mysqli 和 mysql_fetch_object 中 __set() 在 __construct() 之前调用。该报告来自 2009 年,据说已修复,但在我运行的 5.3 版本中,似乎仍然会发生这种情况。这是: https://bugs.php.net/bug.php?id=48487
2) 如果在执行
__set()
方法的过程中抛出异常或发生其他错误,您将得到这个模糊的“can't callX: :__construct()
"消息而不是真实异常/错误消息。我可以这样解决我的问题:
在我的例子中我有点幸运,因为我可以让构造函数运行两次而没有任何问题,但你可能不会在同一条船上。
I have a bit more information on this question, as I ran into the same problem.
1) I found a PHP bug report that documents that in mysqli and mysql_fetch_object __set() is called before __construct(). The report is from 2009 and supposedly was fixed, but in the version of 5.3 I'm running it still seems to happen. Here it is: https://bugs.php.net/bug.php?id=48487
2) If, in the process of executing your
__set()
method you throw an exception or some other error occurs you'll get this vague "can't callX::__construct()
" message instead of the real exception/error message.I could resolve my problem thusly:
I'm a bit lucky in my case because I can let the constructor run twice without any problems, but you might not be in the same boat.