我正在爲php cms編寫一個模塊。在函數(回調函數)中,我可以訪問來自框架代碼的對象。強制訪問__PHP_Incomplete_Class對象屬性
此對象的類型爲__PHP_Incomplete_Class
,因爲會話啓動之前不包括所需的頭文件。我不能在不侵犯核心cms代碼的情況下包含它。
我想知道是否可以訪問對象屬性無論如何(鑄造陣列不工作)。我問這個,因爲我可以看到var_dump()
的值,但使用$object->var
我總是得到空值。
我正在爲php cms編寫一個模塊。在函數(回調函數)中,我可以訪問來自框架代碼的對象。強制訪問__PHP_Incomplete_Class對象屬性
此對象的類型爲__PHP_Incomplete_Class
,因爲會話啓動之前不包括所需的頭文件。我不能在不侵犯核心cms代碼的情況下包含它。
我想知道是否可以訪問對象屬性無論如何(鑄造陣列不工作)。我問這個,因爲我可以看到var_dump()
的值,但使用$object->var
我總是得到空值。
當您序列化尚未包含的類的對象時,會出現此問題。 例如,如果在包含類之前調用session_start。
PHPIncompleteClass對象不能直接訪問,但可以使用foreach,serialize和gettype。 使用PHPIncompleteClass對象調用is_object將導致false。
所以,如果你發現在你的會話中的「__PHP_Incomplete_Class」對象,並在其中的session_load之後你的類,你可以使用這個功能:
function fixObject (&$object)
{
if (!is_object ($object) && gettype ($object) == 'object')
return ($object = unserialize (serialize ($object)));
return $object;
}
這將導致一個可用的對象:
fixObject($_SESSION['member']);
我發現這個技巧可以讓你施放一個對象:
function casttoclass($class, $object)
{
return unserialize(preg_replace('/^O:\d+:"[^"]++"/', 'O:' . strlen($class) . ':"' . $class . '"', serialize($object)));
}
從http://blog.adaniels.nl/articles/a-dark-corner-of-php-class-casting/
所以,你可以這樣做:
$obj = casttoclass('stdClass', $incompleteObject);
,然後訪問屬性爲正常。
您還可以在.htaccess/Apache配置文件中定義unserialize_callback_func
。這樣你就不需要破解任何PHP,但可以按需包含文件。
如果你只是需要從PHP_Incomplete_Class對象訪問原始數據(如類變量),你可以使用foreach黑客,或者你也可以這樣做:
$result_array = (array)$_SESSION['incomplete_object_index'];
echo $result_array['desired_item'];
另外這裏是我的fix_object()函數的版本: 主要更改是代碼中的步驟3:使所有的屬性公開。
當PHP序列化一個對象時,所有私有和受保護的屬性都以兩個空字節作爲前綴!這些空字節是真正的原因,爲什麼不能通過$obj->key
訪問該屬性,因爲它實際上是類似於$obj->{NULL*NULL}key
。
/**
* Takes an __PHP_Incomplete_Class and casts it to a stdClass object.
* All properties will be made public in this step.
*
* @since 1.1.0
* @param object $object __PHP_Incomplete_Class
* @return object
*/
function fix_object($object) {
// preg_replace_callback handler. Needed to calculate new key-length.
$fix_key = create_function(
'$matches',
'return ":" . strlen($matches[1]) . ":\"" . $matches[1] . "\"";'
);
// 1. Serialize the object to a string.
$dump = serialize($object);
// 2. Change class-type to 'stdClass'.
$dump = preg_replace('/^O:\d+:"[^"]++"/', 'O:8:"stdClass"', $dump);
// 3. Make private and protected properties public.
$dump = preg_replace_callback('/:\d+:"\0.*?\0([^"]+)"/', $fix_key, $dump);
// 4. Unserialize the modified object again.
return unserialize($dump);
}
var_dump
將不顯示這些空字節前綴給你,但你可以看到他們使用此代碼:
class Test {
private $AAA = 1;
protected $BBB = 2;
public $CCC = 3;
}
$test = new Test();
echo json_encode(serialize($test));
// Output:
// "O:4:\"Test\":3:{s:9:\"\u0000Test\u0000AAA\";i:1;s:6:\"\u0000*\u0000BBB\";i:2;s:3:\"CCC\";i:3;}"
$test2 = fix_object($test);
echo json_encode(serialize($test2));
// Output:
// "O:8:\"stdClass\":3:{s:3:\"AAA\";i:1;s:3:\"BBB\";i:2;s:3:\"CCC\";i:3;}"
還有你看:
NULL + classname + NULL
NULL + "*" + NULL
我讀過很多建議,就如何解決不完全classobjects,我確實需要解決這些問題我自己,在電子商務項目。
我發現的一個建議是簡單地使用json_decode/json_encode轉換不完整的類,而不預先加載任何東西。不過,我不想冒這個風險,如果有一些老版本的PHP依賴於例如PECL,在http://php.net/manual/en/function.json-encode.php處描述 - 所以我終於成功地制定了我自己的解決方案。
但是,代碼是一種正確地將數據從對象中取出的方法,因此它可能不適合所有需求 - 並且主要首先使用json解決方案(如果它在環境中可用且失敗如果需要的話可以手動處理。
它也遞歸地工作,在我自己的情況下是必需的,以保存整個數組。
/**
* Convert a object to a data object (used for repairing __PHP_Incomplete_Class objects)
* @param array $d
* @return array|mixed|object
*/
function arrayObjectToStdClass($d = array())
{
/**
* If json_decode and json_encode exists as function, do it the simple way.
* http://php.net/manual/en/function.json-encode.php
*/
if (function_exists('json_decode') && function_exists('json_encode')) {
return json_decode(json_encode($d));
}
$newArray = array();
if (is_array($d) || is_object($d)) {
foreach ($d as $itemKey => $itemValue) {
if (is_array($itemValue)) {
$newArray[$itemKey] = (array)$this->arrayObjectToStdClass($itemValue);
} elseif (is_object($itemValue)) {
$newArray[$itemKey] = (object)(array)$this->arrayObjectToStdClass($itemValue);
} else {
$newArray[$itemKey] = $itemValue;
}
}
}
return $newArray;
}
您需要的類,你正試圖從會話
整潔讀取對象後,把在session_start()。我只是喜歡做這樣的黑客東西;) – n3rd 2009-06-08 16:21:06
聰明但「hackish」:]我首先想到了eval(東西)。 – gpilotino 2009-06-08 17:11:09
感謝發佈!注意:它應該是casttoclass('stdClass',$ incompleteObject)。 – Langdon 2010-02-06 22:29:51