Download the PHP package maxkain/eav-bundle without Composer
On this page you can find all versions of the php package maxkain/eav-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package eav-bundle
Eav bundle
This package is a Symfony bundle, it integrates with Doctrine, EasyAdmin, Symfony Forms and Translator component, and you can use it with REST API. But it has no required dependencies, and you can try to use it with any framework and ORM. In this case, you need to implement some adapters. See
ContractsandBridgedirectories.
Contents
- Description
- Installation
- Creating entities
- Attribute
- EAV
- Value
- Main entity
- EavInverter
- Validation
- EavConverter
- Options registry
- EAV Tag
- Query factory
- Usage with EasyAdmin and Forms
- Demo application
Description
The goal of this bundle is to provide the flexible and high performance implementation of EAV (Entity-Attribute-Value) pattern in PHP. You can give the opportunity to the user of your application creating his own attributes and edit them.
Main features:
- Attributes may have any plain type values or enum values, defined by the user. They, also, can be singular or multiple.
- Binding attributes to one or to many categories or tags. For example, you want to show certain attributes of product only for one or more product categories. Also, you can include attributes of parent categories.
- One attribute can be associated with many types of entities and tags.
- Converting and inverting EAV to or from database and client side. Internal input validation.
- Factory to help you create queries for filtering your entities by attributes with tag bindings checking.
- Listener, that checks modified tags, attributes, entities and removes orphaned EAVs from database.
- Ready to use CRUD user interface for EAV, based on Symfony Forms and integrated with EasyAdmin.
Installation
You need PHP version >= 8.1.
This bundle uses AutoconfigureTag, Autowire and AutowireIterator attributes of the Symfony service container. If you have old version of Symfony, and it does not support this attributes, you may write YAML config, for example, or configure it somehow different by yourself.
Creating entities
For example, you have App\Entity\Product\Product entity, and you want to create attribute for it. First, you need to create entities for EAV. It would be nice to create them with Maker bundle, but there is no such functionality for now. Let's create Attribute entity. It can be named as you want, EnumAttribute, StringAttribute, MultiEnumAttribute. But let it be named MyAttribute.
Attribute
Then create entity for EAV.
EAV
There is a string value, but it may be any of scalar types. If you want singular values, change UniqueConstraint fields to ['entity', 'attribute'].
Value
If you want enum values, you need to create entity for the value field.
Then, replace the value field in the MyEav entity:
And add collection of allowed values to MyAttribute entity:
Also, you might need adder and remover for this collection, if you use Forms or anything else, which use PropertyAccessor component.
Main entity
Then, add property to your Product entity:
Apply changes to your database schema by Doctrine migrations or simply by bin/console doctrine:schema:update --force command. Create few attributes in database.
EavInverter
Now you can change your entity attribute values in your services or controllers by EavInverter:
If you use Forms, the violations will be automatically mapped to form fields. And if you have Translator installed, the messages will be translated.
If you need to add only values, without removal exiting, pass withAddOnly parameter to the invert function.
If you pass items as arrays, field names can be configured with reversePropertyMapping option:
Also, we used default EAV entities property names. But you can change them by propertyMapping option:
This mapping is needed for database queries. It would be nice to read options from PHP attributes and reflection at container compile time, but there is no such functionality for now. Although, you will rarely need to change it.
To get the list of allowed attributes for entity, to show it to the user, use findAllowedAttributes method of EavInverter.
Validation
You can restrict input types to one of PHP types:
If ignoreInputEmptyValue is false, then violations will be generated, if value is empty.
EavConverter
Converts collections of EAV entities to client side. Usage is similar to EavInverter.
With convertItemsToArrays option you can convert them to arrays or to EavSingularOutputItem or EavMultipleOutputItem objects .
Options registry
You can hold your options in one place, registry. Also, registry is used by OrphanedEavsListener, which checks and deletes orphaned EAVs, caused by EavTag logic.
You need to create configurator:
Now this options will be loaded by EavOptionsRegistry, when it will be created by the service container. Then, you can receive it anywhere:
By default, the key is EAV FQCN, but, if you need to store many options for one EAV, you can define any string key in the array, returned by the configurator. Also, you can clone options to don't repeat them. All these option will be used for checking by EAV tags.
EAV Tag
Suppose, you have App\Product\Category entity. You can bind it to attribute by attribute tag. Create the tag entity:
Then, add it to MyAttribute property:
Your Categoty should implement EavTagInterface, your Product should implement EavEntityWithTagsInterface and your attribute should implement EavAttributeWithTagsInterface. The method getEavTags of your Product and MyAttribute should look, like this:
If you have ManyToMany Categories, then, like this:
isForAllEavTags method of attribute looks similar.
And you need to add options:
If you have different properties and different options in your entity with the same category entity, you might set tagKey option and pass it value as key of the array, returned by getEavTags.
That's all, the Category is bound.
If you want to include parent's categories attributes, simply, store them all in a dedicated ManyToMany field of your entity and fill the field by the setter of the main category property or by your service, controller, or by doctrine event listener. And don't forget to set EAV property mapping.
The OrphanedEavsListener is enabled by default. It works fast, but you can disable it by enable_orphaned_eavs_listener config of the bundle or by setEnabled method of the listener.
Query factory
Subqueries (semi-joins) are much faster, then joins with group by, if many rows are needed to group.
You may use EavQueryFactory, like this:
Here you pass attributes with values.
If you use EavExpression, ':field' placeholder will be replaced to the value field path.
Don't forget to escape user's input by Doctine's createNamedParameter function.
If you use EavComparison, value argument will be escaped automatically.
By default, all conditions use AND logic, but with EavExpression you may define any DQL condition.
Also, you may use createEavCondition method for more complex logic.
Usage with EasyAdmin and Forms
You may create CRUD for all entities with EasyAdmin tools. See the demo application. And you can use a EavCollectionType form type, which includes the bundle, and it's entry type EavType. You may use EavFieldFactory to create Easy Admin fields:
You may use CSS and form theme of the bundle in your controller or dashboard:
Also, you can apply them to any collection field:
Errors of the EavInverter map to the form correctly. But if you try to validate the value field with Symfony validator by entity attributes, the errors will not be mapped correctly, because the form has another structure. For correctly mapping you may specify constraints directly in form entry options:
And there are other options, you can pass.
If you use EAV tag, the tag field should be earlier, then EAV properties, in the fields order. This is necessary for tags checker could read this field.