LINUX.ORG.RU

[PHP suck of the week] Как всегда, мы не смогли осилить объектную модель


0

0

В общем, есть некий класс. У этого класса есть дети, внуки.

И вдруг мне нужно узнать имя класса, из которого вызывается статический метод. Типа вот:

<?php
class MyParentClass {
  public static function munchName() {
    return strtolower(get_class()); // myparentclass
  }
}

class MyChildClass extends MyParentClass {
}

echo MyChildClass::munchName(); // myparentclass... WTF?!

В сердцах я пошел в багзиллу узнать, что за фигня. И узнал — сначала до них два экрана не доходило, о чем речь, а когда дошло, они радостно сказали, что баг явственно показывает, какая у них долбанутая архитектура, из-за чего они его фиксить не будут. Сам тамошний диалог с багрепортером вызвал стойкие ассоциации с Хлебовводовым.

★★★★★
Ответ на: комментарий от KRoN73

> Соответственно, этот код будет работать автоматически. Без какого-либо участия с моей стороны или костылей.

Эй, друг, ты не понял.
Сообщение создано
Сохранено в базу
Сервер давно перезагрузили
И теперь сообщение надо прочесть из базы, сохранив те классы,которые были

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

>Сообщение создано

Сохранено в базу


Какой пример, такой и ответ. Нужно было пояснить.

У меня в этом случае в БД хранится target_class_name или target_class_id. И опять я не понимаю, в чём проблема.

вообще, объекты не знают откуда они взялись, куда их пишут - нефиг им голову взякой фигней забивать.


Объект должен быть инкапсулированным. Подмена объекта одного типа объектом другого не должна быть заметна снаружи. Соответственно, и методика загрузки объекта должна быть сокрыта.

А во втором случае как раз уходишь на путь, который ведет к стройной системе костылей и подпорок.


Пока так и не увидел ни одного хоть сколько-нибудь достоверной причины для введения костылей. Уж сколько лет использую свой подход, но в данном контексте костылей нет.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> но в данном контексте костылей нет

Вот это костыль: static function load($id) { return object_load(get_called_class(), $id); }. Если Message (или кто-то еще) хочет прочесть информацию об авторе с id=1, какой метод в твоей модели он должен вызвать? Person::load() или Account::load()?

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

Вот это костыль

Это не костыль. Это просто более удобная и логичная запись $object = object_load('class_name', $id). Логичная - потому что скрывается идеологически левая функция :)

Если Message (или кто-то еще) хочет прочесть информацию об авторе с id=1, какой метод в твоей модели он должен вызвать? Person::load() или Account::load()?

$object = $class_name::load($id);
KRoN73 ★★★★★
()
Ответ на: комментарий от no-dashi

Единственный, кого можно спросить об этом - это твой Loader. Но если все рвано спрашивать у Loader'а и потом обращаться к Loader'у, зачем вообще вводить статические методы? И зачем тогда нужен Loader у объекта? Ты просто вводишь лишние сущности.

P.S.: Account берется не из таблицы Accounts, а из «persons join account on persons.id = account.id» :-)

no-dashi ★★★★★
()
Ответ на: комментарий от KRoN73

То есть, ты каждый раз лепишь

{ $classname = loader->getClassName(); $object = $classname::load($id); } фактическиприбегая к макроподстановкам, статическим методам, get_called_class() и прочему вместо простейшего { $object = $loader->load($id); } ???

Запущеный случай :-)

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

зачем вообще вводить статические методы?

Я уже несколько раз в теме писал :) Для удобства записи.

Ты просто вводишь лишние сущности.

Нет. Наоборот, уменьшаю их число. Скажем, скрываю сущность лоадера в повседневной работе.

P.S.: Account берется не из таблицы Accounts, а из «persons join account on persons.id = account.id» :-)

Какая разница? Ну будет в модели класса Account прописан join, хотя это и грязно. Но да, самому так иногда делать приходится, правда, у меня это не join, а мультиполевая запись, типа:

function fields()
{
    return array(
        'persons' => array('id', 'name', 'age'),
        'accounts(person_id)' => array('login', 'group_id'),
    );
}

join'ы - это уже проблема лоадера.

KRoN73 ★★★★★
()
Ответ на: комментарий от no-dashi

То есть, ты каждый раз лепишь

Зачем каждый раз?

Типовой пример: message.php:

class message extends bors_object_db
{
    function fields()
    {
        return array('id', 'time', 'target_class_name', 'target_object_id', 'message');
    }

    function auto_targets()
    {
        return array('target' => 'target_class_name(target_object_id)';
    }
}

show/last/messages.php:

class show_last_messages extends bors_page
{
    function body_data()
    {
        return array('messages' => objects_array('message', array(
            'limit' => 10,
            'order' => '-id',
        )));
    }
}

show/last/messages.html:

<ul>
{foreach from=$messages item="m"}
<li>Message {$m->message()} from {$m->target()->title()}</li>
{/foreach}
</ul>

Где тут запущения? :) Это вполне реальный пример. Который будет работать, если его инсталлировать и дать нужные данные.

То, что в этом топике обсуждается, так это замена

objects_array('message', array('limit' => 10, 'order' => '-id'));
на
message::objects(array('limit' => 10, 'order' => '-id'));

Но претензии у тебя сейчас уже явно не к этому подходу :D

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Но претензии у тебя сейчас уже явно не к этому подходу

Ну да, у меня претензии к использованию статиков там, где они нафиг не сдались, с последующей истерией на предмет get_called_class() и далее по тектсу :-)

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

Ну да, у меня претензии к использованию статиков там, где они нафиг не сдались

Ну так обоснуй, чем вариант:

$messages = message::objects(array('limit' => 10, 'order' => '-id')); 
хуже, чем
$messages = objects_array('message', array('limit' => 10, 'order' => '-id')); 

? :)

Ну, или в общем случае:

$objects = $class_name::objects(array('limit' => 10, 'order' => '-id')); 
против
$objects = objects_array($class_name, array('limit' => 10, 'order' => '-id')); 

с последующей истерией на предмет get_called_class()

Истерия - это фраза «Так вот, get_called_class() позволит сделать то же самое красивее и удобнее. Хотя по сути это будет чисто синтаксический сахар»? :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Ну так обоснуй, чем вариант

$messages = message::objects(array('limit' => 10, 'order' => '-id'));

хуже, чем


$messages = objects_array('message', array('limit' => 10, 'order' => '-id'));



Тем, что место objects(), равно как и objects_array(), не в функции, и уж точне не как static в message, а в лоадере.

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

>Тем, что место objects(), равно как и objects_array(), не в функции, и уж точне не как static в message, а в лоадере.

На колу мочало, начинай сначала :) Лоадеры у нас, вообще, приходят, уходят или могут совсем отсутствовать. Объект должен знать, какой ему лоадер нужен и нужен ли. Произвольный абстрактный лоадер невозможен. В лучшем случае он всё равно будет читать из свойств объекта какой ему нужен лоадер (и нужен ли) и вызывать нужный лоадер. Получается лишняя сущность.

KRoN73 ★★★★★
()
Ответ на: комментарий от trashymichael

>в общем вышло то что вам не хватает всего-то синтаксического сахара

Об этом я с самого начала и говорил: «Так вот, get_called_class() позволит сделать то же самое красивее и удобнее. Хотя по сути это будет чисто синтаксический сахар». И недавно эту фразу повторял.

и в этом вся трагедия?


И в этом нет никакой трагедии :)

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

> Произвольный абстрактный лоадер невозможен. В лучшем случае он всё равно будет читать из свойств объекта какой ему нужен лоадер

В том то и дело, что не будет. При нормальном подходе абстрактный лоадер возможен, и объект ничего не знает о лоадере. Вообще. А все эти свистопляски с get_class_name() у вас из-за того, что вы почему-то решаете передать в прикладную часть объектной модели завязки на то, что находится в другом измерении. А при совсем грамотной обвязке лоадер ничего не знает об объектной модели, как и объектная модель о лоадере.

no-dashi ★★★★★
()
Ответ на: комментарий от no-dashi

>При нормальном подходе абстрактный лоадер возможен

Угу. Когда все объекты одинаковые. А я тут всё больше про практические задачи с произвольными бэкендами.

при совсем грамотной обвязке лоадер ничего не знает об объектной модели, как и объектная модель о лоадере.


Да-да. И лоадеру совсем не обязательно знать, что он грузит и кому отдаёт. Он у нас телепат великий :)

KRoN73 ★★★★★
()
Ответ на: комментарий от anonymous

>оппост

Что-что?

человеку сахару не хватает?


А при чём тут человек?

Выражайтесь яснее. Ибо неясность речи есть признак неясности мысли.

KRoN73 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.