Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> symfony, репозитории, качественный lazy load 
:(
    Опции темы
bars80080
Дата 8.11.2017, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 71
Всего: 315



Добрый день,

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

в общем, имея собственное представление об организации архитектуры веб-приложения, тем не менее понимаю, что до меня это всё кем-то уже реализовывалось, конечно же более умным, да ещё и целой командой разработчиков. сейчас вклинился в разборку с symfony и в принципе много чего нравится, но пока не могу преодолеть момент "как грамотно реализовать систему репозиториев". то что там сделано на автомате не совсем прозрачно работает и трудно понять как заставить механизмы работать так, как хочется.

к примеру:
Код

$em = $this->getDoctrine()->getManager();

$blog1 = $em->getRepository('BloggerBlogBundle:Blog')->findOneBy(array('id' => 11));
$blog2 = $em->getRepository('BloggerBlogBundle:Blog')->findOneBy(array('id' => 12));
$blog3 = $em->getRepository('BloggerBlogBundle:Blog')->findOneBy(array('id' => 11));

даст три запроса в БД, хотя первый и третий идентичны. ну ладно, я конечно могу тут придумать своё хранилище, складывать туда объекты и проверять их наличие. но это фактически приводит к отказу от существующей системы репозиториев и написанию своей. уверен, в доктрине или самом symfony это уже сделано, но прокопаться через доки пока не получается.

вопрос1: как правильно выглядят в symfony запросы, если требуется ленивая загрузка, чтобы лишний раз ничего не грузилось?
вопрос2: можно ли накидать в очередь на загрузку идентификаторов, чтобы они потом загрузились при первом требовании?

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

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

и ещё есть пара смежных вопросов:

на одном ресурсе увидел формулировку, что "Зависимостей между бандлами быть не должно. Они могут зависеть от библиотек. но не от бандлов. ". 
вопрос3: как быть в случае, если используются общие сущности и репозитории?
к примеру, реестр пользователей может потребоваться сразу в нескольких бандлах. дело программиста - не дублировать код, поэтому репозиторий конечно должен быть один. где ему тогда находиться?

вопрос4: как, едрить его, выглядит простой запрос SELECT COUNT(*) FROM .... ?

куда не ткну, все занимаются какой-то анархией: либо выбирают коллекцию объектов (которая может быть нафиг не нужна) и потом уже ->count() от неё даёт число, на ровном месте перенапрягая систему, либо тупо фигачат прямой SQL-запрос чуть ли не в обход подготовки запросов в PDO, то есть выкидывают в мусорку достижения доктрины и симфони

спасибо
PM MAIL WWW   Вверх
_zorn_
Дата 12.11.2017, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 21.8.2007

Репутация: 6
Всего: 12



Цитата(bars80080 @  9.11.2017,  00:45 Найти цитируемый пост)
 в доктрине или самом symfony это уже сделано

Первое непонимание. Симфония к доктриновским репозиториям не имеет никакого отношения. Я вообще думал ты про какие нибудь git репозитории спросить хочешь когда название темы прочитал.

Цитата(bars80080 @  9.11.2017,  00:45 Найти цитируемый пост)
вопрос1: как правильно выглядят в symfony запросы, если требуется ленивая загрузка, чтобы лишний раз ничего не грузилось?

Читай выше - симфония к доктрине, как bash к ubuntu например.

Тебе зарываться в доктриновские доки надо. Либо юзать другую ОРМ если есть возможность.

На вопрос 4 - как то так я трункейт делал
Код

        $con = $em->getConnection();
        $platform = $con->getDatabasePlatform();
        $con->executeUpdate("SET foreign_key_checks = 0;");
        $con->executeUpdate($platform->getTruncateTableSQL('ConnectionHouse'));
        $con->executeUpdate($platform->getTruncateTableSQL('ConnectionStreet'));
        $con->executeUpdate("SET foreign_key_checks = 1;");


Для селекста через бинды тоже есть возможность, но лучше через стандартные методы. Я юзал сырые потому что нету другой возможности.

Добавлено @ 18:02
Цитата(bars80080 @  9.11.2017,  00:45 Найти цитируемый пост)
куда не ткну, все занимаются какой-то анархией

Для того ОРМ и есть чтобы сырые запросы не юзать. Но если оченть надо, то можно   smile 

Это сообщение отредактировал(а) _zorn_ - 12.11.2017, 18:06
PM MAIL   Вверх
_zorn_
Дата 12.11.2017, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 21.8.2007

Репутация: 6
Всего: 12



Цитата(bars80080 @  9.11.2017,  00:45 Найти цитируемый пост)
даст три запроса в БД

Ясен пень, потому что ты именно это и просишь. Или он должен мысли твои прочитать ?
А если между первым и третьим данные поменялись в базе ?
Так и ищи что нибудь по кешингу.

Это сообщение отредактировал(а) _zorn_ - 12.11.2017, 18:14
PM MAIL   Вверх
bars80080
Дата 9.1.2018, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прапор творюет
****
Награды: 1



Профиль
Группа: Завсегдатай
Сообщений: 12022
Регистрация: 5.12.2007
Где: Königsberg

Репутация: 71
Всего: 315



то что я дурак, я и так знаю, иначе бы вопросов не задавал. а на вполне конкретные вопросы желательно всё же давать конкретные ответы

найдены следующие ответы:

Цитата(bars80080 @  8.11.2017,  17:45 Найти цитируемый пост)
вопрос1: как правильно выглядят в symfony запросы, если требуется ленивая загрузка, чтобы лишний раз ничего не грузилось?

в доктрине имеются разные типы запросов, и как всегда в документации чётко не разъяснено по группам их отличия. фактически приходится смотреть прямо в код движка, чтобы разобрать последовательность вызовов.
метод findOneBy() всегда вызывает запрос в БД, а метод find() нет. последний уже использует сохранённый кэш.
поэтому, если возникает нужда запросить что-то с уточняющими параметрами (к примеру, найти запись по id и доп.параметру date), то лучше использовать
Код

        $blog = $em->getRepository('BloggerBlogBundle:Blog')->find($id);

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

Цитата(bars80080 @  8.11.2017,  17:45 Найти цитируемый пост)
вопрос2: можно ли накидать в очередь на загрузку идентификаторов, чтобы они потом загрузились при первом требовании?

нет.
пока таких приёмов не обнаружил. приходится самому накапливать массив идентификаторов

Цитата(bars80080 @  8.11.2017,  17:45 Найти цитируемый пост)
вопрос3: как быть в случае, если используются общие сущности и репозитории?

судя по всему, данный момент является большим размытым пятном архитектуры в симфони. бандлы вроде как предполагают объединение модулей по тематическим признакам, но совершенно при этом упускают разделение системы на уровни. фактически в бандле намешана как логика отображения, так и бизнес-логика, плюс ещё элементарные механизмы забора данных и любые связи.
пока что не вижу возможности для смыслового разделения в рамках данного фреймворка. выделить бизнес-логику в отдельную директорию, а в бандле оставить только отображение - скорее всего вступит в конфликт с самим фреймворком и сделает невозможным его адекватное использование. по сути дела, чтобы всё хорошо проверить, надо постараться сделать два бандла, с единым забором данных. к примеру, один бандл с отображением комментариев к блогу есть, можно ещё добавить подгрузку по ajax через бандл API, и посмотреть, как их удастся скрестить. отслеживая, чтобы не было лишних запросов.
скорее всего, в рамках симфони придётся слить обе темы в один бандл, чтобы не плодить сущности. и считать бандл объединяющим групповым модулем по теме.

Цитата(bars80080 @  8.11.2017,  17:45 Найти цитируемый пост)
вопрос4: как, едрить его, выглядит простой запрос SELECT COUNT(*) FROM .... ?

для адекватного решения с использованием примочек в виде queryBuilder и недопущением перерасхода ресурса пришлось сделать дополнительный репозиторий:

Код

namespace Blogger\BlogBundle\Entity\Repository;

/**
 * CommentCountRepository
 *
 */
class CommentCountRepository extends \Doctrine\ORM\EntityRepository
{
    public function getCountByBlogs($blog_id)
    {
        if(empty($blog_id)) { return array(); }
        
        if(!is_array($blog_id)) {
            $blog_id = array($blog_id);
        }
        $data = $qr = array();
        if(!empty($blog_id)) {
            $blog_id = array_unique($blog_id);
        
            $qc = $this->createQueryBuilder('c')
                   ->select('COUNT(c.id) AS cnt, c.blog_id')
                   ->where('c.blog_id IN (:barr)')
                   ->groupBy('c.blog_id')
                   ->setParameter('barr', $blog_id);

            $qr = $qc->getQuery()->getResult();
        }
        foreach($qr as $v) {
            $data[$v['blog_id']] = intval($v['cnt']);
        }
        foreach($blog_id as $key) {
            $key = intval($key);
            if(!isset($data[$key])) { $data[$key] = 0; }
        }
        
        return $data;
    }
}


а для его поддержки дополнительную сущность:
Код

namespace Blogger\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Mapping\ClassMetadata;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
 * @ORM\Entity(repositoryClass="Blogger\BlogBundle\Entity\Repository\CommentCountRepository")
 * @ORM\Table(name="comment")
 * @ORM\HasLifecycleCallbacks
 */
class CommentCount
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="integer")
     */
    protected $blog_id;
    public function __construct()
    {
    }
}

что попахивает кучей никчёмных классов под одну операцию, поэтому сразу вызывает некоторое неприятие всего движка

Это сообщение отредактировал(а) bars80080 - 9.1.2018, 12:26
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1350 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.