Как создать модель «hasMany» и «belongsTo»? (Такая же, как CakePHP)

#php #cakephp #activerecord

#php #cakephp #activerecord

Вопрос:

В настоящее время я работаю над своей платформой mvc (на PHP). Я видел, что CakePHP имеет возможность использовать функции «belongsTo» и «hasMany». Я пытаюсь создать свою собственную функцию и столкнулся с проблемой.

Допустим, у нас есть таблица встреч (id, где, дата, year_id) и таблица лет (id, год). Я знаю, что этот пример можно было бы сделать с одной таблицей без проблем, но это всего лишь пример.

 class appointment_model extends model{
    public $_belongs_to= array('table'=>'year','field_connector'=>'year_id');
    public $one_value;
}
  

……

 class year_model extends model{
    public $_has_many= array('table'=>'appointment','field_connector'=>'year_id');
    public $many_values;
}
  

….

 class model{

private function select($query=null){
    if(!$query)die("Query cannot be null. Line num: " . __LINE__);
    $results = $this->_db->mysql_select($query);
    if(count($results)==1){
        $one = $this->initialize($results[0]);
        $this->_do_for_other_tables($one);
        return $one;
    }elseif(count($results)>1){
        $returns = array();
        foreach($results as $result){
            $one = $this->initialize($result);
            $returns[] = $this->_do_for_other_tables($one);     
        }
        return $returns;
    }else{
        return null;
    }

}


private function _do_for_other_tables(amp;$one, $rec=1){


    if(property_exists($this, 'many_values')){
        if(!empty($one->many_values))return;
        $many = functions::load_model($this->_has_many["table"]);
        $res = $many->find_by($this->_has_many["field_connector"], $one->id);
        $one->many_values = $res;
    }
    elseif(property_exists($this, 'one_value')){
        if(!empty($one->_belongs_to))return;
        $only_one = functions::load_model($this->_belongs_to["table"]);
        $field = $this->_belongs_to['field_connector'];
        $res = $only_one->find_by('id', $one->$field);
        $one->one_value = $res;
    }

}

}
  

По сути, здесь происходит то, что я вхожу в бесконечный цикл. Есть предложения, как я могу это исправить? Если мне нужно объяснить это подробнее, просто скажите это.

Спасибо :).

Комментарии:

1. Почему вы снова изобрели велосипед? Доктрина делает это из коробки!

2. @Francesco: Это не потому, что вы не хотите знать, как это работает под капотом, чего другие тоже не знают. Я сам создал миллионы фреймворков в соответствии со своими потребностями, потому что все они мне не подходили. То же самое для Vizualni здесь, вероятно…

Ответ №1:

Ваша проблема в том, что вы рассматриваете свойства «hasMany», «belongsTo», «hasOne», «etc» как простые свойства, вместо того, чтобы рассматривать их как отношения 2way. То, что я делал во многих своих собственных фреймворках, — это инициализировать эти свойства вручную программистом, но когда класс инициализируется, вы проверяете эти свойства и генерируете единый объект, который связывает их вместе.

Создайте класс, подобный объекту System_DB_Relationship, и вы поместите одну и ту же копию в две инициализированные модели. Если вы не создаете свои модели в качестве шаблона проектирования Factory, вы можете использовать статическую модель $relationship для хранения ваших отношений. Я склонен использовать заводскую / активную запись, поэтому лучше управлять ими. Теперь, в зависимости от логики вашего базового класса модели, вы можете захотеть поместить флаг в отношение, чтобы сказать: «Эй, это отношение использовалось», чтобы вы не переходили к нему снова.

Другой способ — всегда работать по убыванию. То есть, игнорируйте hasMany, когда он найден, и создайте только прокси-метод для загрузки дочерних элементов, но загрузите все элементы belongsTo, чтобы родительский элемент загружался по умолчанию. Обратите внимание, однако, что эти методы могут стать опасными, если у вас большой набор классов, поэтому то, что я реализую в своих фреймворках, обычно представляет собой параметры загрузки, которые говорят: загружайте X уровней отношений. И когда вам нужен hasMany, вы просто используете __call() для перехвата вызова «$myobject-> подобъекты ()» и просто загружаете их на лету.

Есть множество способов сделать это, просто потратьте время на отслеживание вашего кода вручную, посмотрите, что не имеет смысла, попробуйте что-нибудь, и в конце концов вы к чему-нибудь придете. Но, как сказал Франческо выше, редко бывает полезно изобретать велосипед, если вы не работаете над действительно старыми проектами, которые нельзя преобразовать сразу. Воспринимайте эту работу, которую вы делаете, как возможность стать лучше и узнать, как это работает под капотом…

Комментарии:

1. Спасибо за ваш ответ. Я изменил около 60% своего класса модели, чтобы я мог использовать MySQL select query с двумя выбранными таблицами. Сделать это таким образом было намного проще. Ваш ответ был действительно полезен. Спасибо.

2. Не могли бы вы, пожалуйста, отметить ответ галочкой, спасибо. Дело не в том, что я жадный, просто так, как это должно работать в stackoverflow, и если вы не отмечаете сообщение в качестве ответа, вы снижаете оценку принятия…