2017 © Pedro Peláez
 

library query-constructor

GUI & serializer for Doctrine ORM QueryBuilder

image

informika/query-constructor

GUI & serializer for Doctrine ORM QueryBuilder

  • Wednesday, March 29, 2017
  • by informika
  • Repository
  • 3 Watchers
  • 0 Stars
  • 0 Installations
  • JavaScript
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 2 Versions
  • 0 % Grown

The README.md

query-constructor

Набор инструментов по созданию экземпляра Doctrine QueryBuilder через графический интерфейс с возможностью его сериализации/десериализации., (*1)

Входят следующие инструменты:, (*2)

  • Bundle - бандл Symfony, бэкенд конструктора
  • client - фронтенд конструктора на React-Redux
  • Creator - сервис по созданию экземплярыа QueryBuilder
  • Serializer - сервис по сериализации-десериализации QueryBuilder

Требования

Symfony 2.8+, (*3)

Подключение к проекту (на примере Symfony 2/3)

Регистрация бандла QueryConstructorBundle

# app/AppKernel.php

class AppKernel extends Kernel
{
    public function registerBundles()
    {
        $bundles = [
            ...
            new FOD\QueryConstructor\Bundle\QueryConstructorBundle(),
        ];
        ...
    }
...
}

Конфигурируем роутинг

# app/config/routing.yml
...
fod_query_constructor:
    resource: "@QueryConstructorBundle/Controller/DefaultController.php"
    type:     annotation
    prefix:   /fod

Рендер формы конструктора

В папке /assets пакета содержатся готовые скомпилированные js-файлы., (*4)

Минимальная настройка

  1. Создать симлинк на папку с js-файлами из публичной папки с js (путь по умолчанию: /web/assets/js)
cd web/assets/js
ln -sfn ../../../vendor/friendsofdoctrine/query-constructor/assets query-constructor
  1. Отрисовать форму конструктора через шаблонизатор twig
{{ fod_query_constructor()|raw }}

функция fod_query_constructor, (*5)

Указание собственного пути к js-файлу

Передать опцию scriptPath со ссылкой на js-файл, который будет использован вместо пути по умолчанию /web/assets/js, (*6)

{{ fod_query_constructor({'scriptPath' : '/path/to/myfile.js'})|raw }}

Указание HTML-атрибута id корневого элемента конструктора

Передать опцию htmlId со строковым значением, которое будет использовано вместо id по умолчанию fod-query-constructor, (*7)

{{ fod_query_constructor({'htmlId' : 'custom-constructor-id'})|raw }}

Указание префикса к генерируемым элементам формы

Передать опцию prefix со строковым значением, которое будет использовано в качестве префикса к элементам формы, (*8)

{{ fod_query_constructor({'prefix' : 'form[query]'})|raw }}

В результате атрибут name элемента input получит значение form[query][entity] вместо entity, (*9)

Наполнение конструктора сущностями

Все настройки выполняются через аннотации классов и свойств., (*10)

Выбор сущностей, попадающих в конструктор

Что сделать, (*11)

Указать аннотацию класса QC\Entity., (*12)

Результат, (*13)

  1. Сущность попадет в конструктор. Название в списке выбора - имя класса.
  2. Можно аггрегировать и фильтровать по всем свойствам класса, которые отмечены аннотацией ORM\Column.
  3. Свойства, отмеченные аннотацией ORM\ManyToOne, становятся фильтрами со списками выбора (можно выбрать несколько значений)

Пример, (*14)

В конструктор должна попасть сущность Room с фильтрами Id (integer), Name (string) и Building (список выбора), (*15)

<?php

// ...

use Doctrine\ORM\Mapping as ORM;
use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity()
 */
class Room
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Building", inversedBy="rooms")
     */
    protected $building;
}

Добавление подписи сущности в конструкторе

Что сделать, (*16)

Добавить опцию title аннотации класса QC\Entity., (*17)

Результат, (*18)

Сущность будет назваться, как указано в title. Если опция не задана, используется название свойства в классе., (*19)

Пример, (*20)

Сущность Room должна иметь подпись Помещение, (*21)

<?php

// ...

use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(title="Помещение")
 */
class Room
{
    // ...
}

Добавление подписи свойства в конструкторе

Что сделать, (*22)

Добавить аннотацию свойства QC\Property с опцией title., (*23)

Результат, (*24)

Свойство будет назваться, как указано в title. Если опция не задана, используется название класса., (*25)

Пример, (*26)

Фильтр Building должен иметь подпись Здание, (*27)

<?php

// ...

use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(title="Помещение")
 */
class Room
{
    // ...

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Building", inversedBy="rooms")
     * @QC\Property(title="Здание")
     */
    protected $building;

}

Указание поля с подписью для значений фильтра-выпадающего списка

Что сделать, (*28)

Добавить опцию titleField в аннотацию свойства QC\Property с указанием названия свойства связанной сущности, откуда будут взяты значения подписей., (*29)

Результат, (*30)

Подписи элементов списка будут взяты из указанного свойства связанной сущности. Если опция titleField не задана, подписи берутся из первого поля типа string. Если в сущности такого поля нет и опция не задана явно, выбрасывается исключение., (*31)

Пример, (*32)

Вывести подписи из поля Building.address, (*33)

<?php

// ...

use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(title="Помещение")
 */
class Room
{
    // ...

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Building", inversedBy="rooms")
     * @QC\Property(title="Здание", titleField="address")
     */
    protected $building;

}

Определение свойств для аггрегации, попадающих в конструктор

Что сделать, (*34)

Добавить опцию aggregatable_fields в аннотацию класса QC\Entity с указанием названий свойств, к которым применять аггрегирующие функции. Можно задавать как массив, так и строку (если одно поле)., (*35)

Результат, (*36)

В списке аггрегации будут присутствовать только указанные свойства. Если не задана, присутствует только первичный ключ, (*37)

Пример, (*38)

В список аггрегации должны попасть Id и Name, (*39)

<?php

// ...

use Doctrine\ORM\Mapping as ORM;
use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(aggregatable_fields={"id", "name"})
 */
class Room
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Building", inversedBy="rooms")
     */
    protected $building;
}

Определение свойств для фильтрации, попадающих в конструктор

Что сделать, (*40)

Добавить опцию filterable_fields в аннотацию класса QC\Entity с указанием названий свойств, по которым можно фильтровать. Можно задавать как массив, так и строку (если одно поле)., (*41)

Результат, (*42)

В списках фильтров будут присутствовать только указанные свойства. Если опция не задана, присутствуют все свойства., (*43)

Пример, (*44)

В список фильтрации должен попасть только Name, (*45)

<?php

// ...

use Doctrine\ORM\Mapping as ORM;
use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(filterable_fields="name")
 */
class Room
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Building", inversedBy="rooms")
     */
    protected $building;
}

Исключение свойств для фильтрации, попадающих в конструктор

Что сделать, (*46)

Добавить опцию filterable_fields_except в аннотацию класса QC\Entity с указанием названий свойств, которые исключить из фильтрации. Можно задавать как массив, так и строку (если одно поле)., (*47)

Результат, (*48)

В списках фильтров указанные свойства будут отсутствовать. Если опция применяется совместно с filterable_fields, будут выведены только filterable_fields за исключением свойств, отмеченных в filterable_fields_except., (*49)

Пример, (*50)

В список фильтрации не должен попасть Id, (*51)

<?php

// ...

use Doctrine\ORM\Mapping as ORM;
use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(filterable_fields_except="id")
 */
class Room
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    protected $id;

    /**
     * @ORM\Column(type="string")
     */
    protected $name;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Building", inversedBy="rooms")
     */
    protected $building;
}

Добавление условия по дате для выборки сущности

Что сделать, (*52)

Добавить опцию date_between аннотации класса QC\Entity. В опции указываются названия двух свойств сущности, содержащие даты "от" и "до"., (*53)

Результат, (*54)

К построенному запросу будет добавлено условие AND (:dateReport BETWEEN column1 AND column2), где :dateReport - дата, которая приходит из формы (удобно, если в таблице сущности применен паттерн "Версия реализации")., (*55)

Пример, (*56)

К запросу по сущности Room будет добавлено условие AND (:dateReport BETWEEN fromDate AND toDate) с параметром dateReport., (*57)

<?php

// ...

use FOD\QueryConstructor\Mapping\Annotation as QC;

/**
 * @QC\Entity(date_between={"fromDate", "toDate"})
 */
class Room
{
    // ...

    /**
     * @ORM\Column(type="datetime")
     */
    protected $fromDate;

    /**
     * @ORM\Column(type="datetime")
     */
    protected $toDate;
}

Указание связанных сущностей для фильтров

Что сделать, (*58)

Указать аннотацию класса QC\Entity в связанной сущности (которая отмечена в текущей сущности аннотацией ORM\ManyToOne., (*59)

Результат, (*60)

При задании фильтра можно будет выбрать связанную сущность и ее свойства, настраиваемые по правилам, указанным выше., (*61)

Использование (на примере Symfony 2/3)

Рендер формы конструктора через шаблонизатор Twig

{{ fod_query_constructor()|raw }}

Параметры запроса записываются в скрытый input с именем sqlConstructor (к имени можно добавить префикс - см. настройку рендера выше), (*62)

Получение QueryBuilder из запроса

$queryBuilder = $this->get('query_constructor.creator')->createFromJson($formParams['sqlConstructor']));

Сохранение QueryBuilder в БД

$entity->setSqlFilter(addslashes($this->get('query_constructor.serializer')->serialize($queryBuilder)));

Восстановление QueryBuilder из БД

Например, сериализованный QueryBuilder возвращается $entity->getSqlFilter():, (*63)

$queryBuilder = $this->get('query_constructor.serializer')->unserialize(stripslashes($entity->getSqlFilter()));

Подробнее об инструментах пакета

Creator

Создаёт экземпляр Doctrine QueryBuilder из JSON, (*64)

Формат JSON

{
    "aggregateFunction": "COUNT",
    "entity": "MyClass1",
    "property": "id"
    "conditions": [
        {
            "type": "NONE",
            "entity": "MyClass2",
            "property": "name",
            "operator": "=",
            "value": "John"
        }
    ]
}

Массив conditions[] может быть пустым. Все поля, кроме conditions[].entity - обязательные. Допустимые значения aggregateFunction - COUNT, SUM, MIN, MAX, AVG. Допустимые значения conditions[].type - NONE, AND, OR. Допустимые entity, property определяются из зарегеистрированных провайдеров (см. MetaDataProvider)., (*65)

Serializer

Сериализует свойства экземпляра Doctrine QueryBuilder в виде массива. Обратно десериализует массив в QueryBuilder. Ключи массива:, (*66)

  • dqlParts,
  • parameters,
  • firstResult,
  • maxResults,
  • lifetime,
  • cacheMode,
  • cacheable,
  • cacheRegion

Для успешного записи результата сериализации в БД может потребоваться использовать addslashes() для экранирования 0-символов., (*67)

Bundle

Бэкенд конструктора запросов, регистрация сервисов для Symfony, (*68)

Роуты прилагаемого контроллера для конструктора

  • fod.query_constructor.index - начальные данные для конструктора
  • fod.query_constructor.properties - информация по выбранной сущности (свойства для выборки, фильтров, возможные связи)

Client

Фронтенд-часть конструктора., (*69)

Альтернативы использования:, (*70)

  1. Скомпилированные файлы - расположены в папке /assets проекта (настройка файлов см. выше)
  2. Подключение React-компонента к приложению проекта (см.ниже)

React-компонент конструктора запросов

Установка
  1. Выполнить npm install в корневой папке пакета query-constructor
  2. Добавить в конфигурацию загрузчика babel путь к query-constructor/client
  3. Создать symlink на query-constructor/client в папке с исходниками React основного проекта
  4. В компоненте проекта импортировать компонент QueryConstructor из QueryConstructor.js
  5. Пересобрать js с новым компонентом сборщиком, используемым на проекте
Подключение React-компонента к проекту
import QueryConstructor from '../queryConstructor/QueryConstructor'
...
<QueryConstructor prefix="myform[field]" {...this.props.queryConstructorProps} />
...
Настройка QueryConstructor

Требуются следующие параметры:, (*71)

  • aggregateFunctions - required {'имяКласса': 'Название'} - заполняет список аггрегирующих функций для выборки
  • entities - required {'имяКласса': 'Название'} - заполняет список сущностей для выборки
  • propertiesUrl - required - адрес ресурса, возвращающий свойства сущности в формате Metadata\Registry->get()
  • prefix - строка, добавляемая к имени всех элементов input, создаваемых компонентом

Конструктор формирует JSON, готовый для отдачи в Creator - в input с именем prefix[sqlConstructor], (*72)

The Versions

29/03 2017

dev-master

9999999-dev

GUI & serializer for Doctrine ORM QueryBuilder

  Sources   Download

MIT

The Requires

 

doctrine

29/03 2017

v0.0.1

0.0.1.0

GUI & serializer for Doctrine ORM QueryBuilder

  Sources   Download

MIT

The Requires

 

doctrine