Comments 140
Видимо статья про traits? Я долго ломал голову над тем, что такое типажи, пока не сходил по ссылкам.
+15
А еще я в теги добавил, на всякий случай. Но это не отменяет того факта что трейты это типажи. На всякий случай пометил в начале статьи.
+1
Я б «типажи» на «трейты» все же заменил. Вы же composer композитором не называете
+4
Пусть это будет называться как угодно. В любом случае я подпишусь — да, это то, чего мне постоянно не хватало (множественное наследование). Да. наверняка сейчас есть сложности в поиске откуда ноги растут, но наверняка появятся новые методы мониторинга классов, и проблема исчезнет. Но то, что они это сделали уже сейчас — реально прорыв!
+2
А можете накидать пару-тройку примеров, когда их Вам не хватало?
+3
Основной момент, это именно множественная наследовательность. попробую объяснить на пальцах.
Вот у нас есть класс Животное (буду по русски писать, чтобы не переводить тем, кто не знает англ.)
Есть классы Домашнее_животное и Дикое_животное (производные от Животное).
Есть классы Кошка, Олень.
Сейчас приходится наследственность Собаки и Кошки выглядит так:
class Домашнее_животное extends Животное{}
class Кошка extends Домашнее_животное{}
Так же и Олень
class Дикое_животное extends Животное{}
class Олень extends Дикое_животное{}
И этих последовательных расширений может быть довольно много.
В предложенном же методе можно так писать
class Кошка{
use Животное, Домашнее_животное;
}
А если исходных классов штук 20? Можно довольно гибко всякие кастомные классы получать. Допустим
class Кошка{
use Животное, Домашнее_животное, Кошачьи;
}
Вот у нас есть класс Животное (буду по русски писать, чтобы не переводить тем, кто не знает англ.)
Есть классы Домашнее_животное и Дикое_животное (производные от Животное).
Есть классы Кошка, Олень.
Сейчас приходится наследственность Собаки и Кошки выглядит так:
class Домашнее_животное extends Животное{}
class Кошка extends Домашнее_животное{}
Так же и Олень
class Дикое_животное extends Животное{}
class Олень extends Дикое_животное{}
И этих последовательных расширений может быть довольно много.
В предложенном же методе можно так писать
class Кошка{
use Животное, Домашнее_животное;
}
А если исходных классов штук 20? Можно довольно гибко всякие кастомные классы получать. Допустим
class Кошка{
use Животное, Домашнее_животное, Кошачьи;
}
-1
Не самый удачный пример.
Во первых зачем use Животное и Домашнее_животное если Домашнее_животное уже Животное.
Во первых зачем use Животное и Домашнее_животное если Домашнее_животное уже Животное.
0
Просто я скорее всего двусмысленно выразился здесь:
На самом деле эти классы мы не делаем сразу extends. Их мы наследуем тогда, когда классическим образом идет разработка.
В предлагаемом же варианте эти классы не расширяют сразу базовые классы. То есть весь код выглядит так:
trait Животное{}
trait Дикое_животное{}
trait Домашнее_животное{}
trait Кошачьи{}
trait Парнокопытные{}
и т.д.
class Кошка{
use Животное, Дикое_животное, Кошачьи;
}
Есть классы Домашнее_животное и Дикое_животное (производные от Животное).
На самом деле эти классы мы не делаем сразу extends. Их мы наследуем тогда, когда классическим образом идет разработка.
Сейчас приходится наследственность Собаки и Кошки выглядит так:
class Домашнее_животное extends Животное{}
class Кошка extends Домашнее_животное{}
В предлагаемом же варианте эти классы не расширяют сразу базовые классы. То есть весь код выглядит так:
trait Животное{}
trait Дикое_животное{}
trait Домашнее_животное{}
trait Кошачьи{}
trait Парнокопытные{}
и т.д.
class Кошка{
use Животное, Дикое_животное, Кошачьи;
}
0
И зачем
Не проще ли обойтись одним классом Животное с полем boolean дикое?
Аналогично, есть сомнения в необходимости остальных перечисленных классов.
Есть классы Домашнее_животное и Дикое_животное (производные от Животное).
Не проще ли обойтись одним классом Животное с полем boolean дикое?
Аналогично, есть сомнения в необходимости остальных перечисленных классов.
-3
Может тогда привести в пример несколько тысяч строк кода того же MODX-а, чтобы показать, зачем перешли от использования просто классов к абстрактным, и какую множественное наследование может добавить гибкость?
Это очень простой пример и понятно дело, что далеко не все идеально. Но его не надо буквально воспринимать, а надо просто идею видеть.
Это очень простой пример и понятно дело, что далеко не все идеально. Но его не надо буквально воспринимать, а надо просто идею видеть.
0
О да,
fossies.org/dox/modx-2.2.6-pl/classxPDOObject.html
fossies.org/dox/modx-2.2.6-pl/classmodAccessibleSimpleObject.html
И это вы считаете образцом хорошего ООП дизайна?
fossies.org/dox/modx-2.2.6-pl/classxPDOObject.html
fossies.org/dox/modx-2.2.6-pl/classmodAccessibleSimpleObject.html
И это вы считаете образцом хорошего ООП дизайна?
0
Пусть меня запинают минусами, но xPDO — одно из самых гениальных решений, с которыми мне приходилось работать. И я не просто любитель xPDO, а очень хорошо знающий его, потому знаю, о чем говорю.
-1
Дело не в xPDO (Это же что-то типа библиотеки ORM для PHP?). А дело в архитектуре вашей CMS.
Почему так много классов наследуют объект работы с БД? Где инкапсуляция? Где абстракция от ORM слоя? Почему modEvent, modActiveUser, modScript и т.д. могут невозбранно лезть в БД? Чем это лучше олдового кондового пхп где можно было в любом месте делать mysql_query?
Если весь этот ужас приправить примесями, боюсь даже представить, насколько усугубится этот бардак.
Почему так много классов наследуют объект работы с БД? Где инкапсуляция? Где абстракция от ORM слоя? Почему modEvent, modActiveUser, modScript и т.д. могут невозбранно лезть в БД? Чем это лучше олдового кондового пхп где можно было в любом месте делать mysql_query?
Если весь этот ужас приправить примесями, боюсь даже представить, насколько усугубится этот бардак.
+4
Многие не понимают смысла xPDO как раз потому, что думают, что весь их смысл только во взаимодействии с DB. Но это не так. Все взаимодействие с БД выполняется на уровне пары классов, основной из которых xPDOQuery. Именно он выполняет взаимодействие с DB посредством PDO, расширением которого и является xPDO.
Все же производные от xPDOObject — это не просто объекты для взаимодействия с DB, а полноценные самостоятельные объекты, при чем отлично расширяемые. Но как это часто бывает в веб-проектох, эти сущности хранят свою информацию в базах данных.
К примеру возьмем класс modUser. Понятно дело, что все записи пользователей хранятся в DB. И допустим, мы хотим получить определенного пользователя. Мы выполняем $user = $modx->getObject('modUser', $id); Но в данном случае мы получим не просто данные пользователя, а именно объект пользователя. То есть xPDO получит данные пользователя, и вернет соответствующий объект с этими данными. Если бы нам нужны были только данные пользователя, мы могли бы просто выполнить запрос и получить данные, при этом возможно полностью без класс modUser.
Но работа с таким объектами реально удобна. Получил объект, выполнил какие-то действия с ним, изменил какие-либо его значения, и сохранил его $user->save(); При этом эти объекты могут быть наделены своими уникальными методами, и можно влиять и на все процессы, в том числе установки и чтения переменных, удаления, сохранения и т.п. Но довольно сильная сторона — возможность расширения базовых объектов так, чтобы использовать таблицу исходного объекта. Таким образом мы и функционал расширяем, и базу данных не раздуваем, и за айдишниками не следим. Довольно наглядно про это написано здесь.
Плюс к этому очень мощная штука — связи объектов. То есть я на уровне ключей объектов могу прописать связи, и прописать зависимости (к примеру, удалять зависимый объект или нет). И в дальнейшем, к примеру, вот так работать: $profile = $user->getOne('Profile');
При этом вообще не приходится следить за первичными и вторичными ключами, именами колонок и т.д.
В общем я много что могу рассказать про сильные стороны xPDO. И хочу отметить, что довольно богатый опыт у меня не только с MODX, потому я оцениваю именно в сравнении, а не просто так.
Ну и довольно большим аргумент будет вот этот топик с видюшкой: community.modx-cms.ru/blog/social-engine/9493.html
Аргумент: на все про все написано менее тысячи строк кода. Это при том, что там очень много всяких проверок, управление из админки и т.п.
Все же производные от xPDOObject — это не просто объекты для взаимодействия с DB, а полноценные самостоятельные объекты, при чем отлично расширяемые. Но как это часто бывает в веб-проектох, эти сущности хранят свою информацию в базах данных.
К примеру возьмем класс modUser. Понятно дело, что все записи пользователей хранятся в DB. И допустим, мы хотим получить определенного пользователя. Мы выполняем $user = $modx->getObject('modUser', $id); Но в данном случае мы получим не просто данные пользователя, а именно объект пользователя. То есть xPDO получит данные пользователя, и вернет соответствующий объект с этими данными. Если бы нам нужны были только данные пользователя, мы могли бы просто выполнить запрос и получить данные, при этом возможно полностью без класс modUser.
Но работа с таким объектами реально удобна. Получил объект, выполнил какие-то действия с ним, изменил какие-либо его значения, и сохранил его $user->save(); При этом эти объекты могут быть наделены своими уникальными методами, и можно влиять и на все процессы, в том числе установки и чтения переменных, удаления, сохранения и т.п. Но довольно сильная сторона — возможность расширения базовых объектов так, чтобы использовать таблицу исходного объекта. Таким образом мы и функционал расширяем, и базу данных не раздуваем, и за айдишниками не следим. Довольно наглядно про это написано здесь.
Плюс к этому очень мощная штука — связи объектов. То есть я на уровне ключей объектов могу прописать связи, и прописать зависимости (к примеру, удалять зависимый объект или нет). И в дальнейшем, к примеру, вот так работать: $profile = $user->getOne('Profile');
При этом вообще не приходится следить за первичными и вторичными ключами, именами колонок и т.д.
В общем я много что могу рассказать про сильные стороны xPDO. И хочу отметить, что довольно богатый опыт у меня не только с MODX, потому я оцениваю именно в сравнении, а не просто так.
Ну и довольно большим аргумент будет вот этот топик с видюшкой: community.modx-cms.ru/blog/social-engine/9493.html
Аргумент: на все про все написано менее тысячи строк кода. Это при том, что там очень много всяких проверок, управление из админки и т.п.
-2
UFO just landed and posted this here
Я не ORM отстаиваю, а говорю о реальной сути xPDO и его плюсах.
Если хотите намекнуть на то, ORM — это не по религии, и что pure SQL — это все, и я должен только его проповедовать, то не стоит утруждаться. Я год весь биллинг сотовой компании поддерживал, и с Ораклом научился работать на год раньше, чем с мускулом познакомился, и на чистом SQL, и PL/SQL пишу запросы и т.п. очень хорошо, чтобы что-то с чем-то сравнивать.
Если хотите намекнуть на то, ORM — это не по религии, и что pure SQL — это все, и я должен только его проповедовать, то не стоит утруждаться. Я год весь биллинг сотовой компании поддерживал, и с Ораклом научился работать на год раньше, чем с мускулом познакомился, и на чистом SQL, и PL/SQL пишу запросы и т.п. очень хорошо, чтобы что-то с чем-то сравнивать.
0
UFO just landed and posted this here
Ваше право толковать все так, как вам хочется. И честно — феолетово, что вы там думаете об ORM. Насмотрелись уже всяких противников ORM. Пишите на чем хотите.
-3
Я не говорю, чем оно лучше. Я показываю его суть, плюс связку с MODX.
В глаза брасается вот это:
А что, все работает только на каких-то уникальных прописанных методах типа ->setTitle() или setIsbn()?
Разве нельзя просто $book->set('title', $title); и $book->set('Isbn', $Isbn);?
Или так?
То есть оперируя просто именами переменных, а не создавая уникальные методы?
И вот это: $book->setAuthor($author); (Добавляет объект)
Разве нельзя типа $book->addOne($author); и чтобы ORM-ка сама разобралась что это за объект и куда его сунуть?
А вот чем xPDO лучше, например, моей любимой Doctrine или, скажем, Propel — ни слова не увидел.Не работал ни с одной, ни с другой. Но посмотрел этот мануал: propelorm.org/documentation/04-relationships.html
В глаза брасается вот это:
$author = new Author();
$author->setFirstName("Leo");
$author->setLastName("Tolstoy");
// no need to save the author yet
$publisher = new Publisher();
$publisher->setName("Viking Press");
// no need to save the publisher yet
$book = new Book();
$book->setTitle("War & Peace");
$book->setIsbn("0140444173");
$book->setPublisher($publisher);
$book->setAuthor($author);
$book->save(); // saves all 3 objects!
А что, все работает только на каких-то уникальных прописанных методах типа ->setTitle() или setIsbn()?
Разве нельзя просто $book->set('title', $title); и $book->set('Isbn', $Isbn);?
Или так?
$book->fromArray(array(
'title' => $title,
'Isbn' => $Isbn,
));
То есть оперируя просто именами переменных, а не создавая уникальные методы?
И вот это: $book->setAuthor($author); (Добавляет объект)
Разве нельзя типа $book->addOne($author); и чтобы ORM-ка сама разобралась что это за объект и куда его сунуть?
-3
Ручками эти методы писать не нужно — кодогенераторы по схеме БД или, емнип, генерация схемы по чему-то
Лично мне отдельные акцессоры для каждого поля больше нравятся — автодополнение в IDE, phpdoc, статический анализ и прочие плюшки «статической» типизации.
setAuthor предполагает что связь один к одному. addOne этого не предполагает. По имени функции я не могу преположить, что произойдт если я сделаю два вызова подряд если в схеме связь задана 1:1
Лично мне отдельные акцессоры для каждого поля больше нравятся — автодополнение в IDE, phpdoc, статический анализ и прочие плюшки «статической» типизации.
setAuthor предполагает что связь один к одному. addOne этого не предполагает. По имени функции я не могу преположить, что произойдт если я сделаю два вызова подряд если в схеме связь задана 1:1
+2
Ручками эти методы писать не нужно — кодогенераторы по схеме БД или, емнип, генерация схемы по чему-тоМне этого уже достаточно для того, чтобы сказать, что xPDO лучше представленных ORM-ок, так как нет универсальности, а код разрастается.
Лично мне отдельные акцессоры для каждого поля больше нравятся — автодополнение в IDE, phpdocВ xPDO никто не ограничивает в этом. Своему объекту можно сколько угодно собственных методов прописать.
function setTitle($title){
return $this->set('title', $title);
}
setAuthor предполагает что связь один к одному. addOne этого не предполагает.Как раз очень даже предполагает. И это четко описывается в модели объекта. Если же для него связь прописана один-ко-многим, то используется метод ->addMany(), при чем в таком случае метод ->addOne() для него не выполнится.
-2
Универсальные методы есть, но я их ни разу не использовал. Или обычные акцессоры или тупо публичное свойство без всякой магии.
Я должен ручками писать акцессоры для каждого из полусотни полей?
Не знаю как у вас предполагает. Для меня addOne предполагает добавить одну (из многих) запись за раз, а addMany — сразу много (aka пакетное добавление). Имхо, имя метода должно говорить основные концепции без анализа кода класса. setAuthor мне говорит, что автор может быть только один и этим методом он будет установлен (или перезаписан, если уже есть), а addAuthor (или authors->add) мне говорит, что авторов может быть много, а этим методом автор будет добавлен (неоднозначность возникает только если такой автор уже есть, но обычно хватает беглого взгляда на код, чтобы выяснить набор это или множество)
Я должен ручками писать акцессоры для каждого из полусотни полей?
Не знаю как у вас предполагает. Для меня addOne предполагает добавить одну (из многих) запись за раз, а addMany — сразу много (aka пакетное добавление). Имхо, имя метода должно говорить основные концепции без анализа кода класса. setAuthor мне говорит, что автор может быть только один и этим методом он будет установлен (или перезаписан, если уже есть), а addAuthor (или authors->add) мне говорит, что авторов может быть много, а этим методом автор будет добавлен (неоднозначность возникает только если такой автор уже есть, но обычно хватает беглого взгляда на код, чтобы выяснить набор это или множество)
+1
Я должен ручками писать акцессоры для каждого из полусотни полей?В том-то и дело, что в xPDO этого вообще не требуется. Я всего-лишь показал, что при желании свои методы добавить всегда можно.
По поводу имен методов вообще не буду спорить.
0
Пускай не требуется, но я желаю — ручками должен писать или есть стандартная тулза, которая проанализирует метаданные и «напишет» мне все эти методы?
0
Какие именно «эти»? Хотите данные для колонки указать/изменить, выполнили $object->set($field, $value);
Есть массив данных и хотите все их «скормить» объекту? Пожалуйста. $object->fromArray($data);
Все данные объекта вы можете получить через $object->toArray() или конкретно $object->get($field).
При этом при сохранении он сохранить только те колонки, которые у него прописаны в мета.
Хотите объект добавить, тоже не вопрос. $object->addOne($anotherObject) или если связь один ко многим $object->addMany($objectsArray);
А свои методы пишутся только для уникального функционала. К примеру я хочу обрабатывать особым способом установку значения для какого-то поля. Тогда я в классе объекта пропишу.
Есть массив данных и хотите все их «скормить» объекту? Пожалуйста. $object->fromArray($data);
Все данные объекта вы можете получить через $object->toArray() или конкретно $object->get($field).
При этом при сохранении он сохранить только те колонки, которые у него прописаны в мета.
Хотите объект добавить, тоже не вопрос. $object->addOne($anotherObject) или если связь один ко многим $object->addMany($objectsArray);
А свои методы пишутся только для уникального функционала. К примеру я хочу обрабатывать особым способом установку значения для какого-то поля. Тогда я в классе объекта пропишу.
function set($field, $value){
switch($field){
case 'author':
$value = "Mr.(Ms.) {$value}";
break;
}
return parent::set($field, $value);
}
0
Я привык даже для самых простых таблиц с самой простой логикой писать отдельный класс контейнер. Так проще расширять. В конечном счете большинство ORM-ок так или иначе используют PDO, но добавляют множество своих приятных люшек. Не вижу смысла использовать просто PDO. Если у вас все настолько упирается в производительность, то пожалуйста, пишите на PDO, но это один случай из ста.
0
xPDO — это не PDO, а его расширение. И оно идет со своими плюшками, и да, для каждой таблицы используются свои объекты, и да, их можно расширять, и они могут расширять друг друга.
0
Простите, надо выспаться. Я думал x это название драйвера.
И все равно я не вижу явных преимуществ xPDO над Doctrine.
И все равно я не вижу явных преимуществ xPDO над Doctrine.
0
Каждому свое, и свое не каждому.
+1
Дело в том, что xPDO, хоть и самостоятельная библиотека, тем не менее является неотъемлемой частью MODX Revolution. Это по сути их собственная разработка.
Так как MODX — мой основной фреймворк, то логично, что я и буду использовать xPDO.
Так как MODX — мой основной фреймворк, то логично, что я и буду использовать xPDO.
0
Я как познакомился с Doctrine 2, так вообще ни в одной ORM не только на PHP, но и на Ruby преимуществ не вижу :)
0
xPDO в купе с MODX — это не только ORM, это Acl, источники медиа (не только локальная файловая система, но и облака Amazon3), система пакетов, репозитории, офигенная админка и многое-многое другое. Это программный комплекс.
Просто посмотрите вот этот топик для примера: community.modx-cms.ru/blog/documentation/9611.html
Просто посмотрите вот этот топик для примера: community.modx-cms.ru/blog/documentation/9611.html
0
Видимо отстал от ModX — когда в последний раз крутил (лет 5 назад, наверное, точно не меньше трех), то Drupal мне показался и мощнее, и проще.
0
Лет 5 назад еще даже не Evolution, а более ранняя ветка 0.9 была. Это принципиально разного уровня платформы.
0
Крутил в курах ModX где-то с год назад. Как раз таки эволюшен. Мне не понравилось. Да и в моих проектах она не применима. Разве что для сайтов визиток или других шаблонных сайтов.
+1
Evolution уже как года два не развивается командой MODX (если не считать патчи безопасности).
Revolution — принципиально другая платформа. Могу вас заверить, что я эксперт MODX мирового уровня (не побоюсь таких громких слов) и являюсь MODX Ambassador в Москве.
Разница этих веток настолько принципиальная, что в сообществе даже раскол произошел, и не только в России. Наш community.modx-cms.ru — по большей степени по Revolution.
modx.im (отколовшийся) — по Evolution.
Функционал, который Revolution дает «из коробки» несоизмеримо бОльший по сравнению с Эво. А система пакетов позволяет проекты разрабатывать 100% модульно.
К слову, любой желающий, кто в Москве, может прийти к нам в гости, и я лично отвечу на интересующие вас вопросы и продемонстрирую возможности MODX Revolution.
Revolution — принципиально другая платформа. Могу вас заверить, что я эксперт MODX мирового уровня (не побоюсь таких громких слов) и являюсь MODX Ambassador в Москве.
Разница этих веток настолько принципиальная, что в сообществе даже раскол произошел, и не только в России. Наш community.modx-cms.ru — по большей степени по Revolution.
modx.im (отколовшийся) — по Evolution.
Функционал, который Revolution дает «из коробки» несоизмеримо бОльший по сравнению с Эво. А система пакетов позволяет проекты разрабатывать 100% модульно.
К слову, любой желающий, кто в Москве, может прийти к нам в гости, и я лично отвечу на интересующие вас вопросы и продемонстрирую возможности MODX Revolution.
-1
Пример ужасен. Я по работе использую Symfony и для нее наваяли сервисов/бандлов для интеграци с AWS что не счесть. Не думаю что серьезный проект стоит писать на MODx.
+2
Вот это ужасно?
…
$id = 2; // ID медиасурса
// Получаем объект
$source = $modx->getObject('sources.modMediaSource', $id);
// Инициализируем
$source->initialize();
$url = $source->getObjectUrl('images/image.png');
…
0
Вот это ужасно:
И еще, xpdo включает в себя еще и DI контейнер? Как-то нелогично.
В моих проектах получить путь можно так:
А уже вся логика для работы с файловой системой, использовать AWS или же что-то другое ложится на плечи этого простого сервиса. И настройки все он получает через DI при инициализации.
Подход по сути отличается только реализацией, но не сутью.
public function initialize() {
parent::initialize();
$properties = $this->getPropertyList();
if (!defined('AWS_KEY')) {
define('AWS_KEY',$this->xpdo->getOption('key',$properties,''));
define('AWS_SECRET_KEY',$this->xpdo->getOption('secret_key',$properties,''));
/* (Not needed at this time)
define('AWS_ACCOUNT_ID',$modx->getOption('aws.account_id',$config,''));
define('AWS_CANONICAL_ID',$modx->getOption('aws.canonical_id',$config,''));
define('AWS_CANONICAL_NAME',$modx->getOption('aws.canonical_name',$config,''));
define('AWS_MFA_SERIAL',$modx->getOption('aws.mfa_serial',$config,''));
define('AWS_CLOUDFRONT_KEYPAIR_ID',$modx->getOption('aws.cloudfront_keypair_id',$config,''));
define('AWS_CLOUDFRONT_PRIVATE_KEY_PEM',$modx->getOption('aws.cloudfront_private_key_pem',$config,''));
define('AWS_ENABLE_EXTENSIONS', 'false');*/
}
include_once $this->xpdo->getOption('core_path',null,MODX_CORE_PATH).'model/aws/sdk.class.php';
$this->getDriver();
$this->setBucket($this->xpdo->getOption('bucket',$properties,''));
return true;
}
И еще, xpdo включает в себя еще и DI контейнер? Как-то нелогично.
В моих проектах получить путь можно так:
$repository = $this->getDoctrine()->getManager()->getRepository(Acme:Attachment);
// получаем объект
$attachment = $repository->find($id);
// сервис, который отвечает за логику работы с путями
$pathResolver = $this->get('acme.path_resoler');
$uri = $pathResolver->getFileUri($attachment->getUri());
А уже вся логика для работы с файловой системой, использовать AWS или же что-то другое ложится на плечи этого простого сервиса. И настройки все он получает через DI при инициализации.
Подход по сути отличается только реализацией, но не сутью.
+2
ну так и вы бы показали листинги методов getManager(), getRepository() и т.п.
То, что вы процитировали, это часть объекта, обеспечивающего взаимодействие с облаком AmazoneS3. И это внутренности. Программисту же достаточно использования только этого.
При этом просто смена $id может в итоге повлиять на то, какой объект-провайдер будет инициализирован, будь то файловая система, AmazoneS3 или какой-то другой свой. И от этого этот код не поменяется. Мы выполним все тот же $url = $source->getObjectUrl('images/image.png');
То, что вы процитировали, это часть объекта, обеспечивающего взаимодействие с облаком AmazoneS3. И это внутренности. Программисту же достаточно использования только этого.
$id = 2; // ID медиасурса
// Получаем объект
$source = $modx->getObject('sources.modMediaSource', $id);
// Инициализируем
$source->initialize();
$url = $source->getObjectUrl('images/image.png');
При этом просто смена $id может в итоге повлиять на то, какой объект-провайдер будет инициализирован, будь то файловая система, AmazoneS3 или какой-то другой свой. И от этого этот код не поменяется. Мы выполним все тот же $url = $source->getObjectUrl('images/image.png');
0
Получаем обсолютный путьЭто пять!
+1
xPDO — это ORM по паттерну ActiveRecord, если не ошибаюсь.
0
Ошибаетесь.
PDO (PHP Data Objects) — это php-библиотека (и объект) для взаимодействия с различными базами данными, пришедшая на замену классическим _mysql и т.п. Наверняка же знаете, что методы типа mysql_connect() и т.п. уже устаревшие.
xPDO — это собственная библиотека фреймворка MODX, которая расширяет объект PDO (чисто чтобы обеспечить работу с БД), но сразу имеет в себе и несколько базовых объектов типа xPDOObject, xPDOSimpleObject и т.п.
Плюс весь MODX Revolution построен на этих xPDO-объектах. Тот же пользователь modUser — это в итоге дочерний от xPDOObject.
Все это в купе с отличной админкой, написанной с использованием ExtJS (которая так же славится своей кастомизацией), дает очень мощный инструментарий в руки.
PDO (PHP Data Objects) — это php-библиотека (и объект) для взаимодействия с различными базами данными, пришедшая на замену классическим _mysql и т.п. Наверняка же знаете, что методы типа mysql_connect() и т.п. уже устаревшие.
xPDO — это собственная библиотека фреймворка MODX, которая расширяет объект PDO (чисто чтобы обеспечить работу с БД), но сразу имеет в себе и несколько базовых объектов типа xPDOObject, xPDOSimpleObject и т.п.
Плюс весь MODX Revolution построен на этих xPDO-объектах. Тот же пользователь modUser — это в итоге дочерний от xPDOObject.
Все это в купе с отличной админкой, написанной с использованием ExtJS (которая так же славится своей кастомизацией), дает очень мощный инструментарий в руки.
-2
Индивидуальные акцессоры для полей $comment->setAuthor(new Author('VolCh'). Как вариант — публичные свойства $comment->author = new Author('VolCh')
0
в нормальной ORM (Doctrine к примеру) генерация схемы идет из структуры ваших сущьностей. Тоесть вы описываете класс, а по нему уже генерятся методы.
Опять же если у вас уже есть таблица, одной командой можно сгенерить мэппинг класс. Геттеры/сеттеры умеют генерить почти все популярные IDE.
Это все же дело вкуса, но поддерживать код, использующий только PDO несколько сложнее.
Опять же если у вас уже есть таблица, одной командой можно сгенерить мэппинг класс. Геттеры/сеттеры умеют генерить почти все популярные IDE.
Это все же дело вкуса, но поддерживать код, использующий только PDO несколько сложнее.
+1
В xPDO есть методы и генерации объектов из XML-схемы, и XML из описаний объектов, и объекты из структуры БД, и XML из структуры БД и т.п. Все что угодно.
При этом производные от xPDOObject объекты не требуют никаких методов вообще. Есть set(), get(), save(), remove() и этого достаточно. Есть и другие методы, но «этого достаточно».
На выходе мы получаем чистые заготовки, уже способные выполнять основные функции, и при желании можно их расширять как хочется.
При этом производные от xPDOObject объекты не требуют никаких методов вообще. Есть set(), get(), save(), remove() и этого достаточно. Есть и другие методы, но «этого достаточно».
На выходе мы получаем чистые заготовки, уже способные выполнять основные функции, и при желании можно их расширять как хочется.
0
И что? Вот примеры с которыми Доктрина мне сильно упрощает жизнь:
— генерация миграций (diff структуры базы по сути производится)
— фильтры
— DQL (частенько бывает полезным)
Словом я вообще не понимаю о чем спор. Та же доктрина (как и большинство других ORM-ок) являются обертками над PDO и расширяют его функционал. Пользоваться или нет решать вам, но в своих проектах я всегда буду использовать ORM-мы, так как они сильно облегчают жизнь. Особенно если в один прекрасный день вы захотите перенести часть данных в MongoDB/PHPCR. Так, все что мне нужно будет сделать это изменить описание мэппинга. Логику же переделывать не придется по большей части.
— генерация миграций (diff структуры базы по сути производится)
— фильтры
— DQL (частенько бывает полезным)
Словом я вообще не понимаю о чем спор. Та же доктрина (как и большинство других ORM-ок) являются обертками над PDO и расширяют его функционал. Пользоваться или нет решать вам, но в своих проектах я всегда буду использовать ORM-мы, так как они сильно облегчают жизнь. Особенно если в один прекрасный день вы захотите перенести часть данных в MongoDB/PHPCR. Так, все что мне нужно будет сделать это изменить описание мэппинга. Логику же переделывать не придется по большей части.
+1
Вы наверно плохо проследили диалог. Я совершенно не против ORM и т.п. И вы можете работать со своим любимым инструментарием.
Просто я попытался объяснить что такое xPDO, так как многие ошибочно думают, что его назначение — только взаимодействие с различными DB, что совершенно не так.
И я не хотел кого-то убедить пользоваться именно им. Я просто показал его суть.
Просто я попытался объяснить что такое xPDO, так как многие ошибочно думают, что его назначение — только взаимодействие с различными DB, что совершенно не так.
И я не хотел кого-то убедить пользоваться именно им. Я просто показал его суть.
-1
Вы показали, что xPDO — это ORM или почти ORM.
0
Это расширение ORM. То есть не только грузовик, но еще и груз имеет.
0
Не понял метафору.
0
К тому, что xPDO имеет функционал ORM, но имеет еще дополнительные функциональные объекты.
0
Как по мне ресолвинг пути файла или его URI/URL никак не должен касаться прослойки работы с базой. А если этот вопрос обойти, все тоже самое можно прикрутить к любой другой ORM, да и готовые реализации есть.
Словом, считаю дальнейшую дискуссию не плодотворной, ибо вы просто описываете особенности MODx.
Словом, считаю дальнейшую дискуссию не плодотворной, ибо вы просто описываете особенности MODx.
0
А еще зачем-то придумали какие-то статические классы. Не понятно? Ну да и ладно. Каждому своё, и своё не каждому.
0
Ваш комментарий — отличная иллюстрация, подтверждающая обоснованность опасений, цитирую:
однако многие ведущие разработчики опасались, что типажи будут использоваться не по назначению.
0
Любая организация логики на основе поведения. Когда добавление сущности в иерархию не дает ничего кроме проблем. Пример из моей практики, отчет по нескольким осям.
Пример: есть репорты с группировкой по магазинам->покупателям->покупкам и по магазинам->продавцам->приобретениям. И это вроде бы укладывается в классическое наследование, но есть еще смешанные репорты, где есть и покупатели и продавцы, и вот тут классическое наследование идет боком.
Пример 2: когда ты в рамках DDD пытаешься абстрагироваться от реализации слоя данных, который для разных репозитариев может быть схожим, а может раздичаться, может использовать разные источники хранения, а то и несколько и реализовывать логику объеденения данных.
Пример: есть репорты с группировкой по магазинам->покупателям->покупкам и по магазинам->продавцам->приобретениям. И это вроде бы укладывается в классическое наследование, но есть еще смешанные репорты, где есть и покупатели и продавцы, и вот тут классическое наследование идет боком.
Пример 2: когда ты в рамках DDD пытаешься абстрагироваться от реализации слоя данных, который для разных репозитариев может быть схожим, а может раздичаться, может использовать разные источники хранения, а то и несколько и реализовывать логику объеденения данных.
0
Самый простой пример, лично мне, когда не хватало функционала — сделать из класса, у которого есть родитель, обсервер. Вроде и добавить надо 3 метода, но если надо парочку классов изменить?
0
Вот такой пример. Предметная область — транспорт.
class Transport {...}
class RoadTransport extends Transport {...}
class AirTransport extends Transport {...}
А теперь нужно добавить подтип — пассажирский транспорт и грузовой. И пошли плодить подклассы:
PassengerRoadTransport, CargoRoadTransport, PassengerAirTransport, CargoAirTransport.
Либо наоборот — от транспорта наследовать грузовой/пассажирский, и от них уже наследоваться авто/жд/воздушный:
А можно сделать трейты Cargo и Passenger, в которых реализовать специфичные реализации (виртуальных) методов.
class Bus extends RoadTransport {
use Passenger;
…
}
P.S. Если можно как-то оптимизировать структуру дерева классов без трейтов — подскажите, я что-то не соображу…
class Transport {...}
class RoadTransport extends Transport {...}
class AirTransport extends Transport {...}
А теперь нужно добавить подтип — пассажирский транспорт и грузовой. И пошли плодить подклассы:
PassengerRoadTransport, CargoRoadTransport, PassengerAirTransport, CargoAirTransport.
Либо наоборот — от транспорта наследовать грузовой/пассажирский, и от них уже наследоваться авто/жд/воздушный:
А можно сделать трейты Cargo и Passenger, в которых реализовать специфичные реализации (виртуальных) методов.
class Bus extends RoadTransport {
use Passenger;
…
}
P.S. Если можно как-то оптимизировать структуру дерева классов без трейтов — подскажите, я что-то не соображу…
0
Честно говоря, самое непонятное для меня нововведение в PHP начиная с PHP 3. Как работают разобрался, но вот на практике когда их нужно использовать, а когда нет, так и не понял. Как-то не возникает нужды в множественном наследовании.
+3
Хороший пример использования типажей можно найти во фреймворке Silex. Там есть возможность подключать к приложению модули через них (для удобства).
Сам я тоже еще не столкнулся с задачей где для реализации проекта нужно множественное наследования.
Сам я тоже еще не столкнулся с задачей где для реализации проекта нужно множественное наследования.
0
Я столкнулся в текущем проекте с трейтами. Точнее с трейтом и то он носит экспериментальный характер. Используется для подключения ServiceLocator к произвольному классу. Зачем такая странная реализация — без понятия.
0
Ну как пример, если в Symfony проекте используется множество сервисов, в которые мы через контейнер хотим передавать ObjectManager, лично мне удобнее сделать трейт вида
нежели передавать его через params конструктора.
Ну это просто пример. Таким образом можно включать в классы часто дублируюмую функциональность.
trait ObjectManager
{
protected $manager;
public function setObjectManager (ObjectManager $manager)
{
$this->manager = $manager;
}
protected function getObjectManager()
{
return $this->manager;
}
}
нежели передавать его через params конструктора.
Ну это просто пример. Таким образом можно включать в классы часто дублируюмую функциональность.
+3
Когда я смотрю на ваш пример, мне приходит в голову еще один:
Можно легко подключать возможность работы с кэшем для любого класса через трейты (методы getCacheKey, getCache, setCache)
Можно легко подключать возможность работы с кэшем для любого класса через трейты (методы getCacheKey, getCache, setCache)
+2
Честно говоря не очень нравится подобная идея. К такому классу нужна инструкция: «после инстанцирования объекта не забудьте установить свойство такое-то».
Надо поэкспериментировать с определением конструкторов в трэйте. Или, хотя бы, делать setObjectManager() protected/private и вызывать его в конструкторе класса, а в getObjectManager() проверять на null и бросать NPE для забывчивых. Хотя, конечно, от сценария использования класса зависит, но если (почти) всем методам класса менеджер нужен и его инициализация (почти) обязательна, то место этой инициализации в конструкторе.
Надо поэкспериментировать с определением конструкторов в трэйте. Или, хотя бы, делать setObjectManager() protected/private и вызывать его в конструкторе класса, а в getObjectManager() проверять на null и бросать NPE для забывчивых. Хотя, конечно, от сценария использования класса зависит, но если (почти) всем методам класса менеджер нужен и его инициализация (почти) обязательна, то место этой инициализации в конструкторе.
0
Конструктор-то вы определить в трейте сможете (как __construct(), так и ClassName()).
Но в этом случае вы:
Но в этом случае вы:
- сможете сделать это только в одном трейте изо всех, используемых в классе и его предках.
- не сможете определить конструктор в самом классе.
0
вот на счет второго утверждения вроде бы не совсем так. Вроде бы приоритет метода объявленного в классе выше чем в типаже. Но я лично не пробовал добавлять конструктор в типаж.
+1
1. insteadof… as… не поможет?
2. Обычные методы трэйтов я точно могу в «наследнике» переопределять, а с помощью insteadof as вызывать и методы «родители» из конкретного трэйта даже при конфликте имн в трейтах.
2. Обычные методы трэйтов я точно могу в «наследнике» переопределять, а с помощью insteadof as вызывать и методы «родители» из конкретного трэйта даже при конфликте имн в трейтах.
0
Все верно говорите, с помощью такого способа можно генерировать прокси-трейты. Правда количество методов в конечном классе будет расти из-за добавления альясов в трейте.
0
Видимо я недостаточно ясно выразился.
Конструктор в классе, использующем трейт, молча заместит конструктор из трейта. Конфликт имён конструкторов, определённых в трейтах придётся разрешать явно, через insteadof/as.
Так, что бы определить конструктор в нескольких используемых одновременно трейтах и все они сработали при создании класса, их использующего — не получится.
То, что метод, определённый в трейте, может вообще в принципе выполнять роль конструктора класса для меня выглядит несколько странным.
Конструктор в классе, использующем трейт, молча заместит конструктор из трейта. Конфликт имён конструкторов, определённых в трейтах придётся разрешать явно, через insteadof/as.
Так, что бы определить конструктор в нескольких используемых одновременно трейтах и все они сработали при создании класса, их использующего — не получится.
То, что метод, определённый в трейте, может вообще в принципе выполнять роль конструктора класса для меня выглядит несколько странным.
0
Вот я хотел поэкспементировать насчёт того получится или нет. То есть через инстид определяем алиасы для конструкторов из трейтов, а в конструкторе класса эти алиасы вызываем.
0
Получится, но никаких преимуществ от того, что методы будут называться __construct() не будет:
С тем же успехом мы могли их изначально назвать initFoo() и initBar().
file.php
<?php
trait Foo {
function __construct() { echo "Foo::__construct()\n"; }
}
trait Bar {
function __construct() { echo "Bar::__construct()\n"; }
}
class FooBarClass {
use Foo, Bar {
Foo::__construct as initFoo;
Bar::__construct as initBar;
}
public function __construct() {
echo "FooBarClass::__construct() {\n";
$this->initFoo();
$this->initBar();
echo "}\n";
}
}
$objFooBar = new FooBarClass();
?>
output
X:\>php.exe file.php
FooBarClass::__construct() {
Foo::__construct()
Bar::__construct()
}
FooBarClass::__construct() {
Foo::__construct()
Bar::__construct()
}
С тем же успехом мы могли их изначально назвать initFoo() и initBar().
0
Если это применять к сеттерам, то DI умеет после инициализации сэтить значения. Это зачастую очень удобно. Так что трейты тут очень даже подходят.
0
Не надо никакой инструкции. В случае Symfony 2, просто прописывает зависимость:
services:
MyService:
class: NS\MyBundle\Service\MyService
calls:
- [ setObjectManager, [ @doctrine.orm.entity_manager ] ]
0
Мы у себя трейты исполуем во всяких DTO и еще примерно так gist.github.com/1034079
Хочу добавить, что трейты — это не про наследование. Это про горизонтальное расширение.
Хочу добавить, что трейты — это не про наследование. Это про горизонтальное расширение.
+1
По второмц пример. Я правильно понял, что вы из DataMapper делаете ActiveRecord?
0
не, я бы так делать не стал, но SerializableEntity, Timestampable вполне себе =)
0
Вот это, да, нормальная идея. Дальнейшее развитие интерфейов типа *able. Довольно часто в *able классах приходится писать реализации таких интерфейсов мало чем отличающиеся друг от друга. Правда, нужно будет организовывать какие-то колбэки, которые обязательно должны бы в типажируемом классе или использовать рефлексию, ведь типаж ничего о классе не знает. В общем к типажу нужна инструкция по использованию, соглашения, которым должен отвечать типажируемый класс.
+2
Phython'ом мой любимый язык ещё никто не обзывал…
0
Согласен с распространённым мнением, что это теоретически не столько множественное наследование, сколько умный копипаст.
Другое дело, что на практике в значительном количестве случаев множественное наследование используют именно для копипаста.
Другое дело, что на практике в значительном количестве случаев множественное наследование используют именно для копипаста.
+4
Лучше бы декораторы сделали…
0
Поддерживаю. Очень хотел бы видеть в PHP декораторы похожие на те которые есть в питоне
0
У меня есть реализция PHP декоратора — можешь глянуть в профайле ссылку на статью.
0
В Вашей реализации есть достаточно заметные недостатки, а именно необходимость изменять исходный код декорируемых классов (use TDecorator;).
Такая реализация бесполезна в случае использования сторонних библиотек.
Советую всеже посмотреть как декораторы реализуются в питоне — там это сделано очень красиво за счет метапрограммирования и переопределения функций/методов в рантайме. Именно о такой реализации я и мечтаю.
Такая реализация бесполезна в случае использования сторонних библиотек.
Советую всеже посмотреть как декораторы реализуются в питоне — там это сделано очень красиво за счет метапрограммирования и переопределения функций/методов в рантайме. Именно о такой реализации я и мечтаю.
+3
Тоже самое будет и в Python: невозможно без изменения кода сторонней библиотеки декорировать метод класса.
-1
Совсем не тоже самое.
Допустим у нас есть декоратор:
Тут возможны 2 случая:
1) Вы хотите добавить этот функционал в код всех обьектов некого класса
теперь все вызовы метода будут проходить через декоратор
2) Добавить функционал к одному из обьектов данного класса
И в этом случае вам не надо изменять код самого класса.
Допустим у нас есть декоратор:
def decorate(func):
def world(*args, **kwargs):
func(*args, **kwargs)
print "World"
return world
Тут возможны 2 случая:
1) Вы хотите добавить этот функционал в код всех обьектов некого класса
class Decorated:
@decorate
def speak(self):
print "Hello"
теперь все вызовы метода будут проходить через декоратор
2) Добавить функционал к одному из обьектов данного класса
test = Decorated()
test.speak = decorate(test.speak)
test.speak()
И в этом случае вам не надо изменять код самого класса.
+2
То есть в Вашем понимании вот это:
не изменить исходный код класса?
class Decorated:
@decorate
def speak(self):
print "Hello"
не изменить исходный код класса?
0
Метапрограммирование и переопределение методов в рантайме уже есть ) Без экстеншенов, без магии, с очень низким оверхедом на вызов перехваченого метода. Библиотека Go! AOP к вашим услугам. Только ей под силу добавить к любому вашему классу нужный трейт, не меняя исходный код оригинальных классов.
Пример: берем некоторый класс Example (в нем нет трейтов и интерфейсов), дальше нам захотелось иметь возможность сериализовать объекты данного класса, не меняя исходный код класса. Все просто — создаем трейт SerializableImpl и объявляем совет DeclareParents с интерфейсом Serializable и трейтом SerializableImpl в отношении класса Example, после чего наш класс Example будет имплементировать интерфейс Serializable, в чем можно убедиться проверкой instanceof.
Пример: берем некоторый класс Example (в нем нет трейтов и интерфейсов), дальше нам захотелось иметь возможность сериализовать объекты данного класса, не меняя исходный код класса. Все просто — создаем трейт SerializableImpl и объявляем совет DeclareParents с интерфейсом Serializable и трейтом SerializableImpl в отношении класса Example, после чего наш класс Example будет имплементировать интерфейс Serializable, в чем можно убедиться проверкой instanceof.
0
Лучше бы нативную поддержку юникода сделали…
+1
Так вроде с 5.4 она есть?
0
Нет, всё примерно так же как и раньше — mb_* функциями. А нативную поддержку обещали в 6.0, который неизвестно когда выйдет. тоже очень жду.
0
Нда, посмотрел php.net/manual/en/language.types.string.php#language.types.string.details — какой-то бардак и анархия сейчас :(
0
Угу, и это в 2013 году в языке, который HyperText Preprocessor. В Java полная поддержка unicode была уже в 1998 году.
0
Сдается мне, в том то и проблема, что изначально на юникод не ориентировались, и сейчас приходится переписывать тонны кода и ничего при этом не сломать.
0
Ну Python, Ruby как-то смогли. Начинали с того же примерно, что и в PHP в этом плане.
+1
UFO just landed and posted this here
Python 3 не используется
Спорное утверждение.
python3wos.appspot.com/
Процесс идет, медленно но верно.
0
А при чем тут Python 3? Даже во втором поддержка юникода на все еще недостижимом для php уровне.
0
6.0 не будет. Юникод не получился. До скончания веков mb_ вызывать.
+5
Решение не из лучших, но можно юзать mbstring.func_overload.
+1
Это очень плохое решение, никогда так не делайте. Огромное количество php-библиотек предполагает, что строковые функции оперируют байтами (например, strlen често используется для получения именно размера (двоичной) строки в байтах). Оверлоад эти библиотеки ломает, причём в самых неожиданных местах.
+2
Спасибо, хорошо. Я всегда догадывался, что это еще тот костыль, и сам никогда его не использовал.
0
вот ни разу не попадались подобные библиотеки. Я так понимаю это относится к случаям, когда нужно что-то в поток отправить (аля структуру какую-то), но не уверен. Можете привести пример?
0
а вот я столкнулся с проблемой кодировок тут
sphinxsearch.com/forum/view.html?id=1136
sphinxsearch.com/forum/view.html?id=530
sphinxsearch.com/forum/view.html?id=1136
sphinxsearch.com/forum/view.html?id=530
This is interesting enough so I'll make a translation for those who do not speak Russian
as well.
David points out that mbstring.func_overload, which enables standard PHP string functions
to work OK with UTF-8, might be causing troubles with sphinxapi.php which uses strlen()
when forming request.
He also suggests a fix to sphinxapi.php which would check that and temporarily switch the
encoding to latin1. (which I suppose fixes strlen())
0
UFO just landed and posted this here
Еще из интересных применений трейтов — динамическое их подключение к конечным классам с помощью аспектно-ориентированного программирования. Я как раз недавно сделал поддержку технологии внедрения (Introduction) трейтов в любой класс, а также добавил уникальную возможность перехвата методов в трейтах с помощью генерации прокси-трейтов.
Так что трейты — это хорошо, в сочетании с интерфейсами. А декораторы уже есть благодаря АОП.
Так что трейты — это хорошо, в сочетании с интерфейсами. А декораторы уже есть благодаря АОП.
0
А в чем смысл? Ну тоесть, я не могу представить ситуации, когда может понадобится возможность динамически менять классы приложения. Использовать как плагины? Вместо декораторов? Да и меня немного смущает факт того, что в последнее время все больше и больше людей пытаются решить какие-то проблемы при помощи АОП. Может быть для сервисных задачь оно и подходит (профилирование кода, логирование), но все же я против этого подхода. Хотя это опять же лично мое мнение.
0
Я уже в своей статье на хабре приводил пример АОП, когда достаточно перед методом добавить аннотацию @Cacheable — и он будет кэшироваться, неважно какой метод — динамический, статический, или же вообще в трейте. Это пример номер раз.
Пример номер два (про него еще будет отдельная статья на хабре): есть у вас тонна сущностей доктрины, а вам хочется отдавать их как-то красиво в JSON и начинается вызов тучи геттеров, либо гидрация, а можно сделать это очень элегантно — ко всем классам-сущностям добавить интерфейс
Из реальных примеров — для админки SonataBundle одним классом добавляем журналирование всех действий в админке. Неплохо, да, не меняя оригинальный код?
Пример номер два (про него еще будет отдельная статья на хабре): есть у вас тонна сущностей доктрины, а вам хочется отдавать их как-то красиво в JSON и начинается вызов тучи геттеров, либо гидрация, а можно сделать это очень элегантно — ко всем классам-сущностям добавить интерфейс
JsonSerializable
и трейт с реализацией этого интерфейса. Профит. После этого можно любую сущность заворачивать в REST-интерфейс одним контроллером.Из реальных примеров — для админки SonataBundle одним классом добавляем журналирование всех действий в админке. Неплохо, да, не меняя оригинальный код?
0
В одном из проектов так же реализовывал кеширование сабреквестов для отображения виджетов. Но там все же не AOP а события. Тоесть у вас есть событие onRequest где мы проверям закешили мы уже или нет? Если закэшили то просто отдаем ответ из кэша. И событие onResponse, где мы забираем ответ и смотрим, нужно ли его кешировать.
0
Использование событий влечет за собой написание шаблонного кода, поэтому вы не сможете расширить логику любого метода, если он заранее не написан с учетом возможного расширения. Да и обработка событий добавляет очень большой оверхед. Так что у меня в библиотеке нет никаких событий, хотя если сравнивать по смыслу — то да, в какой-то мере это событие. Только можно создать его в любом месте кода без предварительной подготовки )
0
I also fear that it may fall into the category of often-abused-features such as eval(), goto, constants, the @ operator, class inheritance and regular expressions.
Как можно злоупотреблять константами?
0
При разработке нового проекта возникла необходимость множественного наследования, ну или множественного использования части кода, я очень рад что на этот момент примеси ( трейты) уже были реализованны.
Вот пример: Описывая модели, я столкнулся с тем, что ряд моделей имеют общий код, но в радителя его вставить нет возможности, объясню почему. Модели описывались визуальных объектов, с дальнейшим общением с JavaScript. Была описанна базовая модель Компонент, в котовую вынесена вся общая часть визуальных компонентов (координаты, размеры, ...). Далее описывались сами компаненты, для которых был создан ряд общих родителей (общий для кнопок, у которых было событие нажатия, общий для компонентов, которые могут иметь дочерние элементы, ...) Проблымы появились тогда, когда я добрался до компонентов Изображение и ИзображениеКнопка. По сути ИзображениеКнопка дочерняя сущность от сущности Кнопка, т.к. есть обработчик нажатия, но в ней есть еще описание и весь функционально компонента Изображение, т.к. полностью повторяет функционально и Кнопки и Изображения! Тут я и воспользовался возможностями примесей. Скажу Вам что пхпШторм очень хорошо умеет с ними работать и я еще не пожалел что воспользовался ими. Для большей убедительности, стоит сказать что подобных компонентов у меня несколько, которые содержат полное или частичное дублирование.
Пишу с телефона, прошу прощения за ошибки и опечатки.
Вот пример: Описывая модели, я столкнулся с тем, что ряд моделей имеют общий код, но в радителя его вставить нет возможности, объясню почему. Модели описывались визуальных объектов, с дальнейшим общением с JavaScript. Была описанна базовая модель Компонент, в котовую вынесена вся общая часть визуальных компонентов (координаты, размеры, ...). Далее описывались сами компаненты, для которых был создан ряд общих родителей (общий для кнопок, у которых было событие нажатия, общий для компонентов, которые могут иметь дочерние элементы, ...) Проблымы появились тогда, когда я добрался до компонентов Изображение и ИзображениеКнопка. По сути ИзображениеКнопка дочерняя сущность от сущности Кнопка, т.к. есть обработчик нажатия, но в ней есть еще описание и весь функционально компонента Изображение, т.к. полностью повторяет функционально и Кнопки и Изображения! Тут я и воспользовался возможностями примесей. Скажу Вам что пхпШторм очень хорошо умеет с ними работать и я еще не пожалел что воспользовался ими. Для большей убедительности, стоит сказать что подобных компонентов у меня несколько, которые содержат полное или частичное дублирование.
Пишу с телефона, прошу прощения за ошибки и опечатки.
0
Проблымы появились тогда, когда я добрался до компонентов Изображение и ИзображениеКнопка. По сути ИзображениеКнопка дочерняя сущность от сущности Кнопка, т.к. есть обработчик нажатия, но в ней есть еще описание и весь функционально компонента Изображение, т.к. полностью повторяет функционально и Кнопки и Изображения! Тут я и воспользовался возможностями примесей.IMHO композиция кнопки и изображения выглядело бы здесь более логичным решением.
0
Действительно, несколько странно, что типажи получают возможность иметь состояние, что довольно не верно по идеологии паттерна. То есть, получается, что это что-то соеднее между примесями (mixins) и собственно трейтами.
Боюсь, такая путаница не пойдет на пользу архитектуре, тем более, что примеси дают больше возможностей запутать логику.
Боюсь, такая путаница не пойдет на пользу архитектуре, тем более, что примеси дают больше возможностей запутать логику.
+1
Sign up to leave a comment.
Типажи в PHP: хорошо это или плохо?