__toString магия и принуждение типов - PullRequest
3 голосов
/ 04 марта 2011

Я создал класс Template для управления представлениями и связанными с ними данными.Он реализует Iterator и ArrayAccess и разрешает использование «под-шаблонов» для простого использования, например:

<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 ]

1 голос
/ 04 марта 2011

PHP не поддерживает оператор загрузки .Если вы хотите иметь возможность выполнять сложение (или что-то еще связанное с операторами), вам нужно будет предоставить метод для каждого оператора, которого вы хотите поддерживать.Более чем вероятно, что его реализация в базовом шаблонном классе будет достаточной для обычных случаев, что позволит при необходимости расширить его позже.Хотя использование (string) на вашем объекте является ярлыком, я бы посоветовал против него.

1 голос
/ 04 марта 2011

Эхо пытается повторить результаты $template['foo'] + 1. Поскольку $template['foo'] является объектом типа TemplateData, а 1 является int, вы получаете сообщение об ошибке. В этом случае ((string) $template['foo']) не является "переписыванием", его приведение происходит впервые.

0 голосов
/ 04 марта 2011

Я немного изменил свою реализацию, и, похоже, пока она работает; Я добавил метод __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
);

Может ли кто-нибудь увидеть проблемы с любым из этого или с другим обоснованием альтернативного подхода?

...