Installation:
composer require ollietb/bert-timezone-bundle
(Note: The original README uses Git submodules; prefer Composer for modern Laravel/Symfony integration.)
Register the Bundle:
Add to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
Bert\TimezoneBundle\BertTimezoneBundle::class => ['all' => true],
First Use Case:
Replace Symfony’s default timezone field type in a form:
{{ form_widget(form.timezone, {'type': 'bert_timezone'}) }}
(Renders a Windows-style dropdown with grouped timezones by region/city.)
Form Types:
Extend Bert\TimezoneBundle\Form\Type\TimezoneType for customization:
use Bert\TimezoneBundle\Form\Type\TimezoneType as BaseTimezoneType;
class CustomTimezoneType extends BaseTimezoneType {
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults([
'label' => 'User Timezone',
'attr' => ['class' => 'timezone-selector'],
]);
}
}
Validation:
Use Symfony’s Timezone validator (works with this bundle):
# config/validation.yaml
Bert\TimezoneBundle\Validator\Constraints\Timezone:
message: "Please select a valid timezone."
Dynamic Data: Fetch selected timezone in controllers:
$timezone = $form->get('timezone')->getData(); // e.g., "America/New_York"
$dateTime = new \DateTime('now', new \DateTimeZone($timezone));
API Responses: Normalize timezone strings for consistency:
$normalized = \DateTimeZone::createFromPrestring($rawInput)->getName();
Service Provider:
Register the bundle in AppServiceProvider (Symfony 4+):
public function register() {
$this->app->register(Bert\TimezoneBundle\BertTimezoneBundle::class);
}
Blade Integration: Use the field type in Laravel forms:
{!! Form::select('timezone', null, ['type' => 'bert_timezone']) !!}
Model Casting: Cast timezone strings in Eloquent models:
protected $casts = [
'timezone' => 'string', // Store as "Region/City" format
];
Symfony 2/3 vs. 4+:
deps file setup won’t work in Laravel/Symfony 4+. Use Composer.registerNamespaces with autoload in composer.json:
"autoload": {
"psr-4": {
"Bert\\TimezoneBundle\\": "vendor/ollietb/bert-timezone-bundle/src"
}
}
Timezone Data Staleness:
TimezoneDataProvider:
use Bert\TimezoneBundle\DataProvider\TimezoneDataProviderInterface;
class CustomTimezoneDataProvider implements TimezoneDataProviderInterface {
public function getTimezones() {
return \DateTimeZone::listIdentifiers(); // Fetch fresh data
}
}
config/services.yaml:
Bert\TimezoneBundle\DataProvider\TimezoneDataProvider: '@custom_timezone_data_provider'
JavaScript Dependencies:
// Example: Initialize Select2 on the timezone field
$('.timezone-selector').select2();
Locale Support:
config/packages/bert_timezone.yaml:
bert_timezone:
labels:
"America/New_York": "New York (EDT)"
Verify Data Flow: Dump the rendered HTML to confirm timezone groups:
dd($view->renderFragment(form_row(form.timezone)));
Check for Conflicts: If the dropdown doesn’t render, ensure:
bundles.php.timezone field type.Fallback to Default: Use Symfony’s native type as a fallback:
{% if app.environment == 'prod' %}
{{ form_widget(form.timezone, {'type': 'bert_timezone'}) }}
{% else %}
{{ form_widget(form.timezone) }} {# Default Symfony type #}
{% endif %}
Custom Grouping:
Override TimezoneGroupProvider to reorder/group timezones:
class CustomGroupProvider extends TimezoneGroupProvider {
protected function getGroups() {
return [
'Custom/Group' => ['Europe/London', 'Asia/Tokyo'],
];
}
}
API Endpoints: Create a controller to fetch timezones dynamically:
use Bert\TimezoneBundle\DataProvider\TimezoneDataProviderInterface;
class TimezoneController {
public function __construct(private TimezoneDataProviderInterface $provider) {}
public function getTimezones() {
return response()->json($this->provider->getTimezones());
}
}
Testing: Mock the timezone provider in PHPUnit:
$this->mock(TimezoneDataProviderInterface::class)
->shouldReceive('getTimezones')
->andReturn(['UTC' => 'UTC']);
How can I help you explore Laravel packages today?