Реализация многокорневого вложенного набора для пользователей DBAL.
Эта библиотека предоставляет вам классы записи, чтения и проверки для вложенных наборов с несколькими корневыми узлами в каждой таблице. Опираясь исключительно на Доктрину DBAL.
В отличие от других решений, эта библиотека имеет четкие границы и оставляет разработку программного обеспечения на ваше усмотрение.
Используйте композитор для установки библиотеки
> composer require shopware/dbal-nested-set
Вам всегда нужна конфигурация, которая устанавливает основные имена столбцов вашей реализации:
use Shopware DbalNestedSet NestedSetConfig ;
$ config = new NestedSetConfig (
' id ' , // Primary key column name
' left ' , // left column name
' right ' , // right column name
' level ' // level column name
);
Затем вы можете использовать NestedSetFactory
для создания различных классов библиотеки.
use Shopware DbalNestedSet NestedSetFactory ;
use Doctrine DBAL Connection ;
$ writer = NestedSetFactory:: createWriter ( $ dbalConnection , $ config );
Возможно, вы захотите создать нормализованную схему для вложенных таблиц наборов, это можно сделать с помощью NestedSetTableFactory
. Он создаст базовый DDL для дерева с индексами. Итак, если вы хотите добавить простое дерево со столбцом имени и идентификатором автоинкремента, оно будет выглядеть так:
$ tableFactory = NestedSetFactory:: createTableFactory ( $ connection , $ config );
$ schema = new Doctrine DBAL Schema Schema ();
$ table = $ tableFactory -> createTable (
$ schema ,
' tree ' , // table name
' root_id ' // nested set root id
);
$ table -> addColumn ( ' id ' , ' integer ' , [ ' unsigned ' => true , ' autoincrement ' => true ]);
$ table -> addColumn ( ' name ' , ' string ' , [ ' length ' => 255 ]);
$ table -> setPrimaryKey ([ ' id ' ]);
$ addSql = $ schema -> toSql ( $ connection -> getDatabasePlatform ());
Конечно, это необязательно и может быть выполнено с помощью любого инструмента настройки схемы.
Библиотека предоставляет класс NestedSetWriter
, который содержит все операции вставки, перемещения и обновления. Все операции должны напоминать DoctrineDBALConnection::insert()
и DoctrineDBALConnection::update()
и требовать просто простых данных.
В качестве примера вы можете использовать это для создания дерева
$ writer = NestedSetFactory:: createWriter ( $ dbalConnection , $ config );
// create a Root node
$ writer -> insertRoot ( ' tree ' , ' root_id ' , 100 , [ ' name ' => ' Clothing ' ]);
// create subnodes
$ writer -> insertAsFirstChild ( ' tree ' , ' root_id ' , 1 , [ ' name ' => ' Men ' ]);
$ writer -> insertAsNextSibling ( ' tree ' , ' root_id ' , 2 , [ ' name ' => ' Women ' ]);
$ writer -> insertAsFirstChild ( ' tree ' , ' root_id ' , 2 , [ ' name ' => ' Suits ' ]);
$ writer -> insertAsFirstChild ( ' tree ' , ' root_id ' , 3 , [ ' name ' => ' Dresses ' ]);
$ writer -> insertAsNextSibling ( ' tree ' , ' root_id ' , 5 , [ ' name ' => ' Skirts ' ]);
$ writer -> insertAsNextSibling ( ' tree ' , ' root_id ' , 6 , [ ' name ' => ' Blouses ' ]);
$ writer -> insertAsFirstChild ( ' tree ' , ' root_id ' , 4 , [ ' name ' => ' Jackets ' ]);
$ writer -> insertAsFirstChild ( ' tree ' , ' root_id ' , 4 , [ ' name ' => ' Slacks ' ]);
$ writer -> insertAsFirstChild ( ' tree ' , ' root_id ' , 5 , [ ' name ' => ' Evening Gowns ' ]);
$ writer -> insertAsNextSibling ( ' tree ' , ' root_id ' , 10 , [ ' name ' => ' Sun Dresses ' ]);
А затем используйте средство записи для перемещения узлов.
$ writer -> moveAsNextSibling ( ' tree ' , ' root_id ' , 4 , 7 );
Возможно, вам захочется получить информацию о разных узлах. Это можно сделать с помощью NestedSetTableNodeInspector
.
$ inspector = NestedSetFactory:: createTableNodeInspector ( $ connection , $ config );
$ inspector -> isLeaf ( ' tree ' , ' root_id ' , 9 ); // true | false
$ inspector -> isAncestor ( ' tree ' , ' root_id ' , 1 , 2 ) // true | false
NestedSetQueryFactory
помогает получить набор узлов из дерева. Поскольку в библиотеке нет концепции сущностей, она подготовит для вас только построители запросов, готовые добавлять выборки, соединения и другие условия.
$ queryFactory = NestedSetFactory:: createQueryFactory ( $ connection , $ config );
$ data = $ queryFactory
-> createChildrenQueryBuilder ( ' tree ' , ' t ' , ' root_id ' , 2 )
-> select ( ' * ' )
-> execute ()
-> fetchAll ();
Если вы хотите разрабатывать локально, вам, возможно, придется настроить доступ к базе данных с помощью небольшого сценария оболочки:
#! /usr/bin/env bash
export DB_USER= ' foo '
export DB_PASSWORD= ' bar '
export DB_HOST= ' baz '
export DB_NAME= ' dbal_nested_set '
bin/phpunit