Главная » Статьи » Документация » Для разработчиков
Категории

ORM, Создание моделей и сущностей

Составление запросов

ORM - это програмнная прослойка между базой данных и контроллерами(модулями). ORM позволяет оперировать данными в виде объектов, а не в виде табличных данных, как они храняться в БД. Зачем это нужно? Ответ очень прост - объектами проще манипулировать на уровне ООП приложения(программы).

Основными частями ORM являются:

- Models
- Entities
- DB Driver

Рассмотрим каждую из этих частей подробнее:


Models

/sys/inc/ORM/Models/
Модели служат для описания связей между собой, а так же для описания функций выборки. Каждой таблице в БД должна соответствовать одна модель. Модель представляет из себя класс унаследованный от класса FpsModel. Для того, чтобы стало понятно как должна называться сама модель(класс модели), проще всего привести несколько примеров(имя_таблицы БД = Модель):
news = NewsModel
news_add_fields = NewsAddFieldsModel

Пример
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
<?php /**
 *
 */
class NewsModel extends FpsModel
{
    public 
$Table 'news';

    protected 
$RelatedEntities = array(
        
'author' => array(
            
'model' => 'Users',
            
'type' => 'has_one',
            
'foreignKey' => 'author_id',
          ),
        
'category' => array(
            
'model' => 'NewsSections',
            
'type' => 'has_one',
            
'foreignKey' => 'category_id',
        ),
        
'comments_' => array(
            
'model' => 'Comments',
            
'type' => 'has_many',
            
'foreignKey' => 'entity_id',
            
'additionCond' => array("module = 'news'"),
        ),
        
'attaches' => array(
            
'model' => 'NewsAttaches',
            
'type' => 'has_many',
            
'foreignKey' => 'entity_id',
        ),
    );
}
?>


Entities

/sys/inc/ORM/Entities/
Сущности служат для представления данных. По сути, каждый объект сущности соответствует одной записе в базе данных. А свойства этих объектов соответствуют значениям полей этих записей. Так же как и в случае с моделями, на каждую таблицу в БД должна быть одна сущность. Другими словами, для каждой таблицы в базе данных у нас должна быть модель и сущность(классы модели и сущности). Сущность это класс унаследованный от класса FpsEntity, а так же содержащий описание всех своих свойст(полей) и методов save() и delete(), которые будут служить для сохранения и удаления записей соответственно. Именование сущностей происходит по-тому же принципу, что и моделей, только в конце вместо Model, будет Entity:
news = NewsEntity
news_add_fields = NewsAddFieldsEntity

Пример
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74 
 75 
 76 
 77 
 78 
 79 
 80 
 81 
 82 
 83 
<?php /**
 *
 */
class NewsEntity extends FpsEntity
{
    
    protected 
$id;
    protected 
$title;
    protected 
$main;
    protected 
$views;
    protected 
$date;
    protected 
$category_id;
    protected 
$category null;
    protected 
$author_id;
    protected 
$author null;
    protected 
$comments;
    protected 
$comments_ null;
    protected 
$attaches null;
    protected 
$tags;
    protected 
$description;
    protected 
$sourse;
    protected 
$sourse_email;
    protected 
$sourse_site;
    protected 
$commented;
    protected 
$available;
    protected 
$view_on_home;
    protected 
$on_home_top;
    protected 
$add_fields null;
    protected 
$premoder;
    protected 
$rating;
    
    
    
    public function 
save()
    {
        
$params = array(
            
'title' => $this->title,
            
'main' => $this->main,
            
'views' => intval($this->views),
            
'date' => $this->date,
            
'category_id' => $this->category_id,
            
'author_id' => $this->author_id,
            
'comments' => (!empty($this->comments)) ? intval($this->comments) : 0,
            
'tags' => (is_array($this->tags)) ? implode(','$this->tags) : $this->tags,
            
'description' => $this->description,
            
'sourse' => $this->sourse,
            
'sourse_email' => $this->sourse_email,
            
'sourse_site' => $this->sourse_site,
            
'commented' => (!empty($this->commented)) ? '1' : new Expr("'0'"),
            
'available' => (!empty($this->available)) ? '1' : new Expr("'0'"),
            
'view_on_home' => (!empty($this->view_on_home)) ? '1' : new Expr("'0'"),
            
'on_home_top' => (!empty($this->on_home_top)) ? '1' : new Expr("'0'"),
            
'premoder' => (!empty($this->premoder) && in_array($this->premoder, array('nochecked''rejected''confirmed'))) ? $this->premoder 'nochecked',
            
'rating' => intval($this->rating),
        );
        
        
        if (
$this->id$params['id'] = $this->id;
        
$Register Register::getInstance();
        return 
$Register['DB']->save('news'$params);
    }
    
    
    
    public function 
delete()
    { 
        
$Register Register::getInstance();
        
$attachClass $Register['ModManager']->getModelNameFromModule('newsAttaches');
        
$commentsClass $Register['ModManager']->getModelNameFromModule('Comments');
        
$addContentClass $Register['ModManager']->getModelNameFromModule('newsAddContent');
        
        
$attachesModel = new $attachClass;
        
$commentsModel = new $commentsClass;
        
$addContentModel = new $addContentClass;
        
        
$attachesModel->deleteByParentId($this->id);
        
$commentsModel->deleteByParentId($this->id);
        
$addContentModel->deleteByParentId($this->id);
        

        
$Register['DB']->delete('news', array('id' => $this->id));
    }
}
?>


DB Driver

Драйвер формирует SQL запросы и выполняет их. Дело в то, что модели передают запросы драйверу в виде набора параметров, а задача драйвера превратить эти данные в SQL запрос, понятный движку БД. Например:
Было
 1 
 2 
<?php $this->getDbDriver()->select('news'DB_FIRST, array('cond' => array('id' => 1)));?>

Стало
SELECT * FROM `news` WHERE `id` = 1 LIMIT 1


Пример создания модели и сущности

Допустим мы решили добавить на наш сайт фильмы, а это значит, что нам понадобиться таблица в БД, в которой будут храниться записи, а так же модель и сущность. Для простоты примера, в нашей табличке будет всего два поля:
CREATE TABLE `films` (
`id` INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`title` VARCHAR( 255 ) NOT NULL
ENGINE = InnoDB;

Создаем модель(/sys/inc/ORM/Models/Films.php):
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
<?php /**
 *
 */
class FilmsModel extends FpsModel
{
    public 
$Table 'films';

    protected 
$RelatedEntities = array();
}
?>

Создаем сущность(/sys/inc/ORM/Entities/Films.php):
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
<?php /**
 *
 */
class FilmsEntity extends FpsEntity
{
    
    protected 
$id;
    protected 
$title;
    
    
    
    public function 
save()
    {
        
$params = array(
            
'title' => $this->title,
        );
        
        
        if (
$this->id$params['id'] = $this->id;
        
$Register Register::getInstance();
        return 
$Register['DB']->save('films'$params);
    }
    
    
    
    public function 
delete()
    { 
        
$Register Register::getInstance();
        
$Register['DB']->delete('films', array('id' => $this->id));
    }
}
?>

Как вы могли заметить, массив $RelatedEntities в нашей моделе пуст. Это по-тому, что с нашими фильмами не связанны другие таблицы. Теперь мы можем делать выборку по нашим фильмам(далее мы рассмотрим как сязать наши фильмы и пользователей).
 1 
 2 
 3 
<?php $filmsModel = new FilmsModel;
$film $filmsModel->getById(1);
$films $filmsModel->getCollection(array('title' => 'Terminator'));?>


Связывание моделей

Допустим, со временем, мы решили расширить функционал нашего сайта с фильмами и решили, кроме названия, хранить еще и ID пользователя, который добавил этот фильм. Для этого нам понадобиться расширить нашу таблицу films и немного подправить модель и сущность.
Добавляем поле в таблицу
ALTER TABLE `films` ADD `user_id` INT( 11 ) NOT NULL

А вот как теперь будет выглядеть модель:
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
<?php class FilmsModel extends FpsModel
{
    public 
$Table 'films';

    protected 
$RelatedEntities = array(
        
'author' => array(
            
'model' => 'Users',
            
'type' => 'has_one',
            
'foreignKey' => 'user_id',
          ),
    );
}
?>

Если перевести это на человеческий язык, то получим следующее - автором считается та сущность модели Users, ID которой равен полю user_id из нужной нам записи. А has_one говорит о том, что у каждого видео может быть только один автор. Ну или еще так: допустим мы выбрали из базы видео и хотим узнать кто его добавил. Тогда мы смотрим какой ID стоит у этого видео в поле user_id и затем ищем по этому ID пользователя. Только тут вся работа ложиться на плечи моделей, которые делают это все автоматически. Ухх.. Надеюсь доступно объяснил.

А вот наша сущность:
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
<?php /**
 *
 */
class FilmsEntity extends FpsEntity
{
    
    protected 
$id;
    protected 
$title;
    protected 
$user_id;
    protected 
$author;
    
    
    
    public function 
save()
    {
        
$params = array(
            
'title' => $this->title,
            
'user_id' => intval($this->user_id),
        );
        
        
        if (
$this->id$params['id'] = $this->id;
        
$Register Register::getInstance();
        return 
$Register['DB']->save('films'$params);
    }
    
    
    
    public function 
delete()
    { 
        
$Register Register::getInstance();
        
$Register['DB']->delete('films', array('id' => $this->id));
    }
}
?>

Теперь наши фильмы связаны с пользователями. Но важно понимать, что теперь мы можем выбрать автора видео, используя модель FilmsModel, но не можем выбрать все видео конкретного пользователя, используя модель UsersModel. Ведь мы ничего не меняли в этой моделе. Для того чтобы UsersModel автоматически связывалась с FilmsModel придется подправить ее $RelatedEntities, добавив туда что-то вроде:
 1 
 2 
 3 
 4 
 5 
<?php 'films' => array(
    
'model' => 'Films',
    
'type' => 'has_many',
    
'foreignKey' => 'user_id',
)
?>
Для разработчиков Просмотров: 6485 Комментариев: 0