Symfony Bundle - AndanteProject
A Symfony Bundle to integrate thephpleague/period into Doctrine and Symfony Form.
Symfony 5.4-6.x and PHP 8.0.
Via Composer:
$ composer require andanteproject/period-bundle- Persist
Period,DurationandSequenceon your DB; - Persist
Periodas a JSON field or a doctrine embeddable object effortless (and it is allowed to benull!!). - Doctrine DQL functions.
- Use
Periodin Symfony Forms its Form Type; - Works like magic ✨.
After install, make sure you have the bundle registered in your symfony bundles list (config/bundles.php):
return [
/// bundles...
Andante\PeriodBundle\AndantePeriodBundle::class => ['all' => true],
/// bundles...
];This should have been done automagically if you are using Symfony Flex. Otherwise, just register it by yourself.
The bundle is going to register period, duration and sequence doctrine types to allow you to map Period
, Duration and Sequence objects to the database.
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use League\Period\Duration;
use League\Period\Period;
use League\Period\Sequence;
/**
* @ORM\Entity()
*/
class Meeting
{
/**
* @ORM\Column(type="period", nullable=true)
*/
private ?Period $period = null;
/**
* @ORM\Column(type="duration", nullable=true)
*/
private ?Duration $duration = null;
/**
* @ORM\Column(type="sequence", nullable=true)
*/
private ?Sequence $sequence = null;
}These types are going to create a JSON field on your database. If you want Period to have a column for startDate
and a separate column for endDate, check the Embeddable mapping down below.
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use League\Period\Period;
/**
* @ORM\Entity()
*/
class Meeting
{
/**
* @ORM\Embedded(class="League\Period\Period", columnPrefix="period_")
*/
private ?Period $period = null;
}This is going to create 3 different columns on your database like period_start_date, period_end_date
and period_boundary_type instead of a JSON field. If you want to use some different names for yout mapping, check
the configuration of this bundle. null. It's a feature expected in Doctrine v3. But, with some magic under the hood, this
bundle allows you to use nullable Period anyway. 👍
No matter the kind of mapping you are using for your Period (type or embedded), you can use these DQL functions to access Period properties:
PERIOD_START_DATE()to accessperiod.startDate, likePERIOD_START_DATE(meeting.period);PERIOD_END_DATE()to accessperiod.endDate, likePERIOD_END_DATE(meeting.period);PERIOD_BOUNDARY_TYPE()to accessperiod.boundaryType, likePERIOD_BOUNDARY_TYPE(meeting.period).
Use Andante\PeriodBundle\Form\PeriodType as a Form like you are used to. This bundle is shipped with no form theme, so
it's up to you to build your form theme.
<?php
declare(strict_types=1);
use Andante\PeriodBundle\Form\PeriodType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type;
use Symfony\Component\Form\FormBuilderInterface;
class EventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', Type\TextType::class)
->add('period', PeriodType::class)
;
}
}type: string default: [), allowed values: [), (], (), []
which boundary type to be used if none has been selected via boundary_type_choice.
$builder->add('period', PeriodType::class, [
'default_boundary_type' => '()',
]);type: bool default: false
Whether to include or not a BoundaryTypeChoiceType to let the user to choice the BoundaryType. This is false by
default. To change which boundary type should be use to create the Period, check out default_boundary_type option.
$builder->add('period', PeriodType::class, [
'boundary_type_choice' => true,
]);type: string default: start
How form child handling startDate property should be called.
$builder->add('period', PeriodType::class, [
'start_date_child_name' => 'custom_start_date_form_child_name',
]);type: string default: end
How form child handling endDate property should be called.
$builder->add('period', PeriodType::class, [
'end_date_child_name' => 'custom_end_date_form_child_name',
]);type: string default: boundary
$builder->add('period', PeriodType::class, [
'boundary_type_child_name' => 'custom_boundary_type_form_child_name',
]);How form child handling boundaryType property should be called.
type: string default: Symfony\Component\Form\Extension\Core\Type\DateTimeType
Which form type to be used for startDate property. You can replace it with something custom.
use App\Form\MyDateTimeType;
$builder->add('period', PeriodType::class, [
'start_date_form_type' => MyDateTimeType::class,
]);type: string default: Symfony\Component\Form\Extension\Core\Type\DateTimeType
Which form type to be used for endDate property. You can replace it with something custom.
use App\Form\MyDateTimeType;
$builder->add('period', PeriodType::class, [
'end_date_form_type' => MyDateTimeType::class,
]);type: array default: []
Additional options to be used for the startDate form child.
$builder->add('period', PeriodType::class, [
'start_date_options' => [
'label' => 'A different Label',
// + whatever option allowed by DateTimeType
],
]);type: array default: []
Additional options to be used for the endDate form child.
$builder->add('period', PeriodType::class, [
'end_date_options' => [
'label' => 'A different Label',
// + whatever option allowed by DateTimeType
],
]);type: array default: []
Additional options to be used for the boundaryType form child.
$builder->add('period', PeriodType::class, [
'boundary_type_options' => [
'label' => 'A different Label',
// + whatever option allowed by Andante\PeriodBundle\Form\BoundaryTypeChoiceType
],
]);type: bool default: true
Additional options to be used for the boundaryType form child.
$builder->add('period', PeriodType::class, [
'allow_null' => false,
// Allow to trigger an error when your Period property is not nullable.
]);This bundle is build thinking how to save you time and follow best practices as close as possible.
This means you can even ignore to have a andante_period.yml config file in your application.
However, for whatever reason, use the bundle configuration to change most of the behaviors as your needs.
andante_period:
doctrine:
embedded_period:
default:
start_date_column_name: start_date # default: null
# Column name to be used on database for startDate property.
# If set to NULL will use your default doctrine naming strategy
end_date_column_name: end_date # default: null
# Column name to be used on database for endDate property.
# If set to NULL will use your default doctrine naming strategy
boundary_type_column_name: boundary_type # default: null
# Column name to be used on database for update boundaryType property.
# If set to NULL will use your default doctrine naming strategy
entity: # You can use per-entity configuration to override default config
App\Entity\Event:
start_date_column_name: starting_at
end_date_column_name: ending_at
App\Entity\Meeting:
start_date_column_name: start
end_date_column_name: endBuilt with love ❤️ by AndanteProject team.