Делимся секретами создания сайтов

паттерн ActiveRecord

Давайте обсудит решения проблем проектирования сложных Web приложений

Ответы: 18 → “паттерн ActiveRecord”

  1. Алексей Некторович Ответить

    и как упростить себе жизнь =) Вы используетепаттерны и какие ????
    как реализована ваша mvc система ????? и нужно ли мне выкладывать сюда исходники c примерами будут ли они интересны ????

  2. Алексей Некторович Ответить

    я предлагаю разобрать паттерн ActiveRecord =)

  3. Андрей Codeator Ответить

    А что собственно его разбирать-то?
    http://en.wikipedia.org/wiki/Active_record_pattern

    На php в чистом виде невозможен =) (настолько, насколько реализован в тех-же rails)

  4. Алексей Некторович Ответить

    да это понятно -) интересно разабрать реализации его на PHP c исходниками =)

  5. Алексей Некторович Ответить

    кто что использует кому что нравиться =) кто чего дописал =)

  6. Алексей Некторович Ответить

    у кого как связи в между таблицамиреализуються =)

  7. Плиско Вячеслав Ответить

    Андрей Codeator Копосов улыбнуло :)
    руби по сравнению с php находится к низшей весовой категории. на php можно реализовать даже больше вещей чем на ruby.
    вещь довольно эллементарная и делается в течении нескольких часов, остальное время нужно тратить на хаки.
    я в ближайшее время планирую заняться велосипедостроением и выложу это дело в блоге, но пока делаю другой мопэд.

  8. Андрей Codeator Ответить

    Хмм…. несогласен.
    Ruby не низшая категория, а функциональный язык. Да, там всё объекты.
    Насколько я знаю AR, лучшая его реализация (и насколько мне известно первая) Ruby-On-Rails, позже вышел PHP-On-Trax, который пытался перенести функционал ROR в PHP, но помешала одна огромная проблема.

    В Ruby ВСЁ объекты, в PHP такого в принципе нет. Это принципиально разные вещи, поэтому AR в PHP это лишь приближённая адаптация данного паттерна.

    А в РНР, как вы верно заметили, без хаков не сделаешь))

    З.Ы. Сам приверженец РНР, выпускаю уже 2-ю версию велосипеда где всё вышеописанное есть, правда с хаками, ORM понравился в ZF, если не видел – посмотри. Да, в Kohana Framework ничего тоже.

    Связи реализуются примерно так:

    $oNews = new Model_News();
    $oNews->has_many('comments', array('id', 'id'));

    function has_many(string $table_name, array/string $link){

    }

    К сожалению реализация заведомо сложных моделей пока в разработке.

    Да, в модели только геттеры и сеттеры, т.е.

    class News_Model extends Core_Model{ //всё, это уже AR, т.к. Core_Model//в свою очередь наследуется от Core_Active_Record

    protected $title;

    public function getTitle(){
    return $this->title;
    }

    public function setTitle($title){
    $this->title = $title;
    }
    }

    Потом что-то типа этого:

    $oNews->load(array('id',4));
    $oNews->setTitle('new_title');
    $oNews->update();

    Ну и всё =)

  9. Плиско Вячеслав Ответить

    ну и при чём тут объекты. AR можно и в процедурном стиле реализовать, я видел и такое.
    в ROR тоже всё на костылях держится, потому так производительность страдает, оно красиво только снаружи, а народ в ruby последнее время склоняется к merb

  10. Alexander Zubakov Ответить

    Хм, вот вопрос, почему же этот паттерн нельзя реализовать на PHP в полной мере? Я сам этот паттерн не использовал, но, судя по описанию, все вполне реализуемо, без особый проблем. Может, в Википедии не все?

  11. Плиско Вячеслав Ответить

    кстати, в роре как раз он реализован не ООПэшно, там метод find, в который передаётся хэш массив, а должно быть так
    user.limit(5).offest(5).find_all_by_name('ruby');
    и сравнения в статьях неадекватные.
    обычно руби очень хвалят те, кто непостиг мощи php

  12. Андрей Codeator Ответить

    а php хвалят те, кто не достиг мощи в руби =)
    были-бы руки прямые, а там уже на любом языке можно

  13. Плиско Вячеслав Ответить

    ты же сам писал
    >В Ruby ВСЁ объекты, в PHP такого в принципе нет.
    >поэтому AR в PHP это лишь приближённая адаптация данного паттерна.
    >ORM понравился в ZF
    это свидетельствует о твоей неквалифицировонности в данном вопросе. раз уж влез с ROR, так хотя бы отвечал по делу, а ты похоже даже не знаком как выглядит AR в ROR изнутри, потому и незнаком с костылями :(
    AR в чистом виде ограничивает разработчика в использовании мощи SQL.
    ну хотя бы
    $ar = TableName::find(1);
    $ar->title = 'new title';
    $ar->save();
    получается что нужно делать 2 запроса, первый на селект, второй на апдейт. или же городить костыль – ленивую инициализацию и дополнительную кучу кода.

  14. Андрей Codeator Ответить

    >это свидетельствует о твоей неквалифицировонности в данном вопросе. раз уж влез с ROR, так хотя бы отвечал по делу
    не увидел сабжа по делу. На ROR писал пару вещей, но вероятно не таких, где можно было-бы найти костыли, или вставить.

    >получается что нужно делать 2 запроса, первый на селект, второй на апдейт
    а иначе никак наверное) можно конечно один на апдейт чистым SQL, но причём тут тогда AR?
    для таких вещей кэширование есть.

  15. Плиско Вячеслав Ответить

    >для таких вещей кэширование есть.
    это и есть хаки для повышения скорости и удобства ;)
    >А в РНР, как вы верно заметили, без хаков не сделаешь))
    так что язык здесь ни причём.

    >На ROR писал пару вещей, но вероятно не таких, где можно было-бы найти костыли, или вставить.
    а ты внутрь AR заглядывал? ruby != ROR

  16. The Dude Ответить

    к сообщению #2
    Можешь и повыкладывать – глянуть всегда интересно

  17. Вячеслав Шиндин Ответить

    Только что набросал с нуля, только представляю себе это не как отдельный ActiveRecord паттерн, а как кусок цельной системы, в которой всё ООП начинается с одного базового класса, в данном случае обозвал его Environment.

    <?

    class Environment {
    }

    abstract class Database extends Environment {
    }

    abstract class ActiveRecord extends Database {

    private $properties;
    private $relations;

    public function __call($method, $params) {
    // TODO: handle getByXxx(), find(), massUpdate, massDelete
    echo get_class($this);
    echo "<pre>";
    print_r($this);
    echo "</pre>";
    }

    public function __get($property) {
    /*if () {
    return related object
    } elseif () {
    return field
    } else {
    return other property
    }*/
    // raise exception
    }

    public function __set($property, $value) {
    // по аналогии с __get, только запись
    }

    // CURD (use PDO extension)

    final public function create() {
    //$args = func_get_arg();
    echo "create";
    }

    final public function update() {
    echo "update";
    }

    final public function replace() {
    echo "replace";
    }

    final public function delete() {
    echo "delete";
    }

    final public function save() {
    echo "save";
    }

    }

    abstract class AbstractField extends Database {

    private $value;

    //abstract public function validate();
    //abstract public function formField();

    public function setValue($value) {
    $this->value = $value;
    //$this->validate();
    }

    public function getValue() {
    return $this->value;
    }

    }

    class AutoIncrementField extends AbstractField {
    }

    class StringField extends AbstractField {

    public function __construct($maxLength = 255) {
    }

    }

    class TextField extends AbstractField {
    }

    abstract class Relation extends AbstractField {
    }

    class HasMany extends Relation {
    }

    class HasOne extends Relation {
    }

    class ManyToMany extends Relation {
    }

    class Article extends ActiveRecord {

    public function __construct() {
    $this->id = new AutoIncrementField;
    $this->title = new StringField;
    $this->content = new TextField;
    $this->author = new HasOne;
    }

    }

    class Author extends ActiveRecord {

    public function __construct() {
    $this->id = new AutoIncrementField;
    $this->name = new StringField(15);
    $this->articles = new HasMany;
    }

    }

    $author = new Author;
    $author->getById(1);

    $article = new Article;
    $article->create(array('title' => 'Hello!', 'content' => 'Coming soon.', 'author' => $author));

    /*
    Переопределить ActiveRecord::__get и ActiveRecord::__set так, чтобы чтение и запись происходили прозрачно через Fields-объекты
    Т.е. через $author->name = 'Slava'; произойдёт запись в $author->name->setValue('Slava') соответствующего объекта, унаследованного от AbstractField
    */

    /*
    Кстати, есть же ещё Doctrine ORM, кто-нибудь её опробовал в деле?
    А ещё года 2-3 назад мне очень нравился Propel.
    На Java хорошая разработка Hibernate, её порт на Python – SQLAlchemy, а для ленивых – Elixir.

    Вот только сейчас я больше склоняюсь писать чуть сложные запросы в чистом виде, без всяких ООП Query-конструкторов, в методах MVC-моделей, используя PDO расширение, неплохо защищающее от SQL injectionов.
    */

Ответить