Installation
composer require crovitche/swiss-geo-bundle
Add to config/bundles.php:
return [
// ...
Crovitche\SwissGeoBundle\SwissGeoBundle::class => ['all' => true],
];
Database Configuration
Ensure your config/packages/doctrine.yaml includes:
dbal:
url: '%env(DATABASE_URL)%'
# Enable LOAD DATA INFILE (required)
server_version: '8.0'
profiling: '%kernel.debug%'
Docker Setup (if using Meilisearch)
Add to docker-compose.yml (as per README):
services:
meilisearch:
image: getmeili/meilisearch:v1.5
ports:
- "7700:7700"
environment:
- MEILI_ENV=development
First Data Import Run the console command to fetch and import Swiss addresses:
php bin/console swiss-geo:import
Verify data in swiss_geo_address, swiss_geo_street, etc. tables.
Configure Meilisearch Client
In config/packages/swiss_geo.yaml:
swiss_geo:
meilisearch:
host: 'http://meilisearch:7700'
api_key: '' # Leave empty for dev
Index Addresses
php bin/console swiss-geo:meilisearch:index
Query in Controller
use Crovitche\SwissGeoBundle\Service\AddressSearchService;
public function autocomplete(Request $request, AddressSearchService $search)
{
$query = $request->query->get('q');
$results = $search->search($query, 5); // Limit to 5 results
return $this->json($results);
}
Entity Mapping
Extend Crovitche\SwissGeoBundle\Entity\Address for custom fields:
use Crovitche\SwissGeoBundle\Entity\Address as BaseAddress;
#[ORM\Entity]
class CustomerAddress extends BaseAddress
{
#[ORM\Column]
private ?string $customerId;
// Getters/Setters...
}
Querying Local Data Use Doctrine repositories:
$addresses = $entityManager->getRepository(Address::class)
->findBy(['locality' => 'Zurich'], ['postalCode' => 'ASC']);
Bulk Operations
Use LOAD DATA INFILE via custom queries or the bundle’s built-in commands:
php bin/console swiss-geo:import --update
Autocomplete Field Type Create a custom form type:
use Crovitche\SwissGeoBundle\Form\Type\AddressAutocompleteType;
$builder->add('address', AddressAutocompleteType::class, [
'meilisearch_service' => $this->container->get('swiss_geo.meilisearch'),
'label' => 'Customer Address',
]);
Validation Validate against stored addresses:
use Crovitche\SwissGeoBundle\Validator\Constraints\ValidSwissAddress;
#[Assert\ValidSwissAddress]
private ?string $address;
Custom DQL Queries
$query = $entityManager->createQuery(
'SELECT a.locality, COUNT(a) as count
FROM App\Entity\CustomerAddress a
GROUP BY a.locality
ORDER BY count DESC'
);
$stats = $query->getResult();
Materialized Views Create a scheduled job to pre-aggregate data:
php bin/console swiss-geo:stats:generate
Meilisearch Performance
LIKE queries.php bin/console swiss-geo:meilisearch:rebuild
LOAD DATA INFILE Restrictions
LOCAL for large imports (check secure_file_priv).my.cnf:
[mysqld]
local-infile=1
secure-file-priv="/tmp"
Data Freshness
php bin/console swiss-geo:import --update
swiss_geo_last_updated table for discrepancies.Command Verbosity Enable debug logs for imports:
php bin/console swiss-geo:import --verbose
Meilisearch Logs
Check Meilisearch dashboard (http://localhost:7700) for indexing errors.
Doctrine Events
Listen for swissGeo.postImport to validate data:
$eventDispatcher->addListener('swissGeo.postImport', function (PostImportEvent $event) {
if ($event->hasErrors()) {
// Handle errors (e.g., notify admin)
}
});
Custom Data Sources Override the default data provider:
# config/packages/swiss_geo.yaml
swiss_geo:
data_provider: App\Service\CustomSwissGeoProvider
Address Enrichment
Extend Address entity with computed fields:
#[ORM\Column]
private ?bool $isResidential;
public function __construct()
{
$this->isResidential = false; // Default
}
Geocoding Use the bundle’s built-in geocoder:
$geocoder = $this->container->get('swiss_geo.geocoder');
$coordinates = $geocoder->geocode('8000 Zurich');
Environment Variables
Override Meilisearch host in .env:
SWISS_GEO_MEILISEARCH_HOST=http://custom-meilisearch:7700
Partial Imports
Filter by canton (e.g., ZH for Zurich):
php bin/console swiss-geo:import --canton=ZH
Schema Updates Use migrations for custom tables:
php bin/console make:migration
How can I help you explore Laravel packages today?