__toString魔法和类型强制

时间:2011-03-03 22:23:35

标签: php type-conversion tostring magic-methods

我已经创建了一个 Template 类来管理视图及其相关数据。它实现了IteratorArrayAccess,并允许“子模板”以便于使用,如下所示:

<p><?php echo $template['foo']; ?></p>
<?php foreach($template->post as $post): ?>
    <p><?php echo $post['bar']; ?></p>
<?php endforeach; ?>

无论如何,我认为创建一个名为 hash() 的类非常有用,而不是使用内联核心函数,例如date()TemplateData,它将充当模板中存储的任何数据的包装。

这样,我可以添加一些常用的格式化方法列表,例如:

echo $template['foo']->asCase('upper');
echo $template['bar']->asDate('H:i:s');
//etc..

当通过控制器中的$template['foo'] = 'bar';设置值时,'bar'的值将存储在其自己的TemplateData对象中。

我使用了魔法__toString()所以当你回显一个TemplateData对象时,它会转换为(string)并转储它的值。但是,尽管mantra 控制器和视图不应该修改数据,每当我做这样的事情时:

$template['foo'] = 1;
echo $template['foo'] + 1; //exception

它死于Object of class TemplateData could not be converted to int;除非我重新 $template['foo']到一个字符串:

echo ((string) $template['foo']) + 1; //outputs 2

排除了必须跳过那个篮圈的目的。 是否存在此类行为存在的变通方法,或者我应该这样做,是否偶然阻止了视图中的数据修改?

3 个答案:

答案 0 :(得分:1)

Echo试图回应$template['foo'] + 1的结果。由于$template['foo']TemplateData类型的对象,而1int,因此您收到错误。在这种情况下,((string) $template['foo'])不是“重铸”,它是第一次投射。

答案 1 :(得分:1)

PHP不支持operator loading。如果您希望能够执行添加(或与此相关的任何其他操作员),则需要为要支持的每个操作员提供方法。很可能在基本模板类上实现它就足以满足常见情况,允许在以后必要时进行扩展。虽然在您的对象上使用(string)是一种捷径,但我建议不要这样做。

答案 2 :(得分:0)

我稍微改变了我的实现,它似乎暂时有效;我已将__invoke()方法添加到TemplateData类,该类返回$_data属性,未更改,无需进行类型转换。所以在实践中:

//in controller
$template['foo'] = 'bar';
$template['abc'] = 123;

//in view
echo $template['foo']();                       //bar
echo $template['foo']->asHash('md5');          //37b51d194a7513...
echo $template['abc']();                       //123
echo $template['abc']() + 123;                 //246
echo $template['abc']->asHash('md5');          //202cb962ac5907...

//__invoke also takes $function and $arguments for alternative syntax
echo $template['foo']('asHash', array('md5')); //37b51d194a7513...

我想,既然我征服了这座山,我的下一步就是以某种方式允许链接:

echo $template['foo']->asHash('md5')->asCase('upper');

然而,这似乎很难做到。跟踪“连锁状态”是我之前尝试过但没有成功的事情。在某种意义上,__invoke()会很容易(但很混乱):

echo $template['foo'](
    array('asHash', 'asCase'),          //ordered array of method names
    array(array('md5'), array('upper')) //ordered array of method argument arrays
);

任何人都可以看到这方面的问题,或其他方法的其他推理吗?