Pommbundle Связь с другим столом

Для моего проекта я использую pommbundle для своего проекта Symfony, и у меня есть вопрос:

Например:

    СТОЛ Каталог:
    id = 1
    имя = тест
    webinfo = 2

    ТАБЛИЦА Информация:
    ID = 1
    webid = 2
    textinfo = ОК
    textmore = это тест

Связь

 Catalogue.webinfo = Info.webid 

Если моя сущность имеет отношение к другой сущности, определенной в схеме, и я хочу, чтобы объект содержал всю информацию, как получить доступ к информации, потому что дамп "Каталог" возвращает только целое число для "вебинфо". Нужно ли создавать свой собственный метод? В комплекте есть метод?

Можно ли показать базовый пример для использования в symfony2?

Спасибо вам

2 ответа

Решение

Pomm не является ORM и поэтому не предоставляет метод для автоматического выбора отношений.

Этот выбор сделан из-за простого состояния привычек большинства программистов:

$blog_posts = $orm->getBlogPosts(); // SELECT * FROM blog.post;

foreach ($blog_posts as $blog_post) {
    printf(
        "The post titled '%s' has been written by '%s'.\n",
        $post->getTitle(),
        $post->getAuthor()->getName() // SELECT * FROM blog.author WHERE author_id = $*
    );
}

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

Вы можете сделать то же самое в SQL только с одним запросом:

SELECT
  title,
  published_at,
  … -- other fields
  a AS author
FROM
  blog.post p
  LEFT JOIN blog.author a USING (author_id)

Это выведет строки как:

       title        |      published_at      |  …  |                    author
Gone with the wind  |  2010-04-04 13:43:02…  |  …  | ("Jules Vernes","jules.vernes@gmail.com", … )

Postgres может возвращать строку Author непосредственно в наборе результатов постов в блоге, это намного более эффективно, чем предыдущее решение, но это может вызвать проблемы с производительностью, если записи автора большие. Может быть интересно добровольно ограничить количество авторских полей, извлекаемых в сообщениях в блоге, возможно, достаточно просто названия. Давайте выполним такой запрос в модели поста блога:

class PostModel extends Model
{
    // …

    public function getWithAuthor()
    {
        // HINT: this is bad practice, read below.
        $sql = <<<SQL
select P.post_id, P.title, …, A.name AS author_name
from blog.post P
    left join blog.author A using (author_id)
SQL;

        return $this->query($sql);
    }

В контроллере становится легко получать сообщения в блоге с дополнительной информацией об авторе:

$blog_posts = $this->get('pomm')['my_session']
    ->getModel(PostModel::class)
    ->getWithAuthor();

foreach ($blog_posts as $post) {
    printf(
        "Post '%s' has been written by '%s'.\n",
        $post['title'],
        $post['author_name']
    );
}

Но этот метод не очень переносим, ​​поскольку имя каждого отношения (таблицы) жестко запрограммировано, как и проекция (поля в части SELECT). Изменение структуры базы данных разрушит этот запрос. Вот способ обойти это:

class PostModel extends Model
{
    // …

    public function getWithAuthor(Where $condition = null)
    {
        $condition = (new Where)->andWhere($condition); // empty condition and empty condition => true.
        $sql = <<<SQL
select {projection}
from   {post} P
  left join {author} A using (author_id)
where {condition}
SQL;

        $projection = $this->createProjection()           // use Post fields
            ->setField('author_name', 'A.name', 'text');  // add a new field with its type
        $author_relation = $this->getSession()
            ->getModel(AuthorModel::class)                // get author relation name
            ->getStructure()
            ->getRelation();

        $sql = strtr(                                     // transform the SQL
            $sql,
            [
                '{projection}'      => $projection->formatFieldsWithFieldAlias("P"),
                '{post}'            => $this->structure->getRelation(),
                '{author}'          => $author_relation,
                '{condition}'       => $condition,
            ]);

        return $this->query($sql, $condition->getValues(), $projection);
    }

Что если со вчерашнего дня нам нужно получить все сообщения блога с указанием их имени?

$blog_posts = $this->get('pomm')['my_session']
    ->getModel(PostModel::class)
    ->getWithAuthor(new Where("published_at > $*::timestamptz", [new \DateTime('yesterday')]));

Также можно извлечь весь вложенный экземпляр Author, просто изменив проекцию в методе:

$projection = $this->createProjection()
    ->setField('author', 'A', 'blog.author');

ПРИМЕЧАНИЕ. Тип поля выше - это таблица, в которой начинается строка. Создание таблицы в Postgres означает создание типа.

В контроллере:

foreach ($blog_posts as $post) {
    printf(
        "Post '%s' has been written by '%s'.\n",
        $post['title'],
        $post['author']['name']
    );
}

Postgres это ОРМ.

Спасибо вам за все, у меня есть только вторая ошибка в моем коде. Исправление:

public function findWithJointureAll(Where $condition = null)
{
    $famille_model = $this
        ->getSession()
        ->getModel('\AppBundle\Entity\MyDb1\PublicSchema\FamilleModel')
        ;

    $condition = (new Where)->andWhere($condition);

    $sql ="
    select
        {projection}
    from
        {ssfamille} ssf
        inner join {famille} fam ON ssf.\"Famille\" = fam.\"ID\" where {condition}";

    $projection = $this->createProjection()
        ->setField('test', 'fam','"Famille"')
        ;

    $sql = strtr(
        $sql,
        [
            '{ssfamille}'    => $this->structure->getRelation(),
            '{famille}'      => $famille_model->getStructure()->getRelation(),
            '{projection}'   => $projection->formatFieldsWithFieldAlias('ssf'),
            '{condition}'    => $condition,
        ]
    );

    return $this->query($sql,$condition->getValues(),$projection);
}

Я хочу просто добавить $projection->formatFieldsWithFieldAlias ​​('ssf') и кавычки, потому что имя базы в верхнем регистре...

Спасибо за ваш комплект, он просто идеален!

Другие вопросы по тегам