cubetools/cube-custom-fields-bundle
Installation
composer require cubetools/cube-custom-fields-bundle
Ensure Composer is globally installed and your project is up-to-date.
Enable the Bundle
Add the bundle to config/bundles.php (Laravel 5.4+) or AppKernel.php (older versions):
CubeTools\CubeCustomFieldsBundle\CubeToolsCubeCustomFieldsBundle::class => ['all' => true],
Configure Routing
Add the routes in routes/web.php (Laravel 5.4+):
use CubeTools\CubeCustomFieldsBundle\Resources\routes\all.php;
Define Custom Fields
Create a config/custom_fields.yml file (or use ignore_errors: true if the file is optional):
custom_fields:
my_entity:
- { name: "custom_field_1", type: "text", label: "Custom Field 1" }
- { name: "custom_field_2", type: "number", label: "Custom Field 2" }
First Use Case Use the bundle to dynamically add custom fields to an entity form. For example, in a Symfony form builder:
use CubeTools\CubeCustomFieldsBundle\Form\Type\CustomFieldsType;
$builder->add('custom_fields', CustomFieldsType::class, [
'entity' => 'my_entity',
'mapped' => false,
]);
Entity-Specific Custom Fields
Use the CustomFieldsType form type to attach custom fields to any entity dynamically. Pass the entity name as a configuration option:
$builder->add('custom_fields', CustomFieldsType::class, [
'entity' => 'user_profile',
'mapped' => true, // Maps fields to the entity
]);
Field Validation Validate custom fields using Symfony’s validation constraints. Define constraints in the YAML config:
custom_fields:
my_entity:
- { name: "email", type: "email", label: "Email", constraints: { NotBlank: {}, Email: {} } }
Data Persistence Store custom field data in a separate table or as JSON in the entity’s database column. Use Doctrine listeners or repository methods to handle serialization/deserialization:
// Example: Custom Doctrine listener to handle custom fields
$entity->setCustomFields(json_encode($customFieldData));
Admin Panel Integration Use the bundle to add custom fields to admin forms (e.g., SonataAdmin, EasyAdmin). Example for EasyAdmin:
$builder->add('custom_fields', CustomFieldsType::class, [
'entity' => 'product',
'label' => 'Product Custom Fields',
]);
API Endpoints Expose custom fields via API using Symfony’s serializers or Laravel’s API resources. Example:
// In a Laravel resource
public function toArray($request)
{
return [
'custom_fields' => $this->resource->getCustomFields(),
];
}
Frontend Integration Use the bundle’s JavaScript assets (if provided) or build custom frontend logic to handle custom fields in forms. Example with Vue.js:
// Fetch custom fields for an entity
axios.get(`/api/custom-fields/my_entity`).then(response => {
this.customFields = response.data;
});
Doctrine Entities Extend your entity to include custom fields. Example:
/**
* @ORM\Column(type="json")
*/
private $customFields = [];
public function getCustomFields(): array
{
return $this->customFields;
}
public function setCustomFields(array $customFields): void
{
$this->customFields = $customFields;
}
Symfony Forms
Customize the CustomFieldsType form type by extending it:
use CubeTools\CubeCustomFieldsBundle\Form\Type\CustomFieldsType as BaseCustomFieldsType;
class ExtendedCustomFieldsType extends BaseCustomFieldsType
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'custom_option' => 'value',
]);
}
}
Localization Localize field labels and placeholders by using Symfony’s translation system:
custom_fields:
my_entity:
- { name: "description", type: "textarea", label: "app.custom_fields.description" }
Translations in resources/translations/messages.en.yml:
app.custom_fields.description: "Product Description"
YAML Configuration Errors
custom_fields.yml to be valid YAML. Use ignore_errors: true in config.yml to avoid crashes if the file is missing or invalid:
imports:
{ resource: custom_fields.yml, ignore_errors: true }
Field Naming Conflicts
Doctrine Lifecycle Events
prePersist and preUpdate events to avoid data loss or corruption.Form Mapping Issues
mapped: true, ensure the entity has a method to handle custom field data (e.g., setCustomFields). Otherwise, the form submission will fail silently.Caching
custom_fields.yml:
php artisan cache:clear
Check Configuration
Verify the custom_fields.yml is correctly loaded. Add debug logs in config.yml:
imports:
{ resource: custom_fields.yml }
Then check Symfony’s debug toolbar or logs for errors.
Form Errors If custom fields don’t appear in the form, ensure:
bundles.php/AppKernel.php.Database Issues If custom fields aren’t saved, check:
setCustomFields method is called.Reusable Field Types Define reusable field types in YAML to avoid repetition:
custom_fields:
reusable_type:
- { name: "reusable_field", type: "text", label: "Reusable Label" }
Then reference them in other entities:
custom_fields:
my_entity:
- { name: "field_1", type: "reusable_type" }
Default Values Set default values for custom fields in YAML:
custom_fields:
my_entity:
- { name: "status", type: "choice", label: "Status", choices: { active: "Active", inactive: "Inactive" }, default: "active" }
Conditional Fields
Use Symfony’s ConditionalFieldBuilder to show/hide fields based on other inputs:
$builder->add('custom_fields', CustomFieldsType::class, [
'entity' => 'order',
'conditional_fields' => [
'shipping_address' => ['if' => 'is_shipping_same_as_billing', 'is' => true],
],
]);
Field Groups Organize custom fields into groups for better UX:
custom_fields:
my_entity:
- { name: "group_billing", type: "group", label: "Billing Information" }
- { name: "billing_address", type: "text", label: "Address", group: "group_billing" }
Testing
Test custom fields with PHPUnit by mocking the bundle’s services or using the CustomFieldsType directly:
$formFactory = $this->get('form.factory');
$form = $formFactory->create(CustomFieldsType::class, null, [
'entity' => 'test_entity',
]);
Performance For entities with many custom fields, consider lazy-loading or pagination in forms/APIs to improve performance.
Security Sanitize custom field inputs to prevent XSS or SQL injection, especially if fields are rendered directly in templates:
{{ form_row(form.custom_fields) | escape }}
How can I help you explore Laravel packages today?