Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Geo Bundle Laravel Package

braune-digital/geo-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install Dependencies Run:

    composer require braune-digital/geo-bundle jms/serializer-bundle sonata-project/admin-bundle braune-digital/translation-base-bundle
    

    Ensure doctrine/orm is also installed (required for Doctrine integration).

  2. Enable the Bundle Add to config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 3):

    BrauneDigital\GeoBundle\BrauneDigitalGeoBundle::class => ['all' => true],
    
  3. Configure Geonames API Key Add to config/packages/braune_digital_geo.yaml:

    braune_digital_geo:
        geonames_user: 'YOUR_GEONAMES_USERNAME'
    
  4. Generate Sonata Admin Extensions Extend the bundle for custom fields/actions:

    php bin/console sonata:easy-extends:generate --dest=src BrauneDigitalGeoBundle
    

    Register the extended bundle in AppKernel.php (Symfony 3) or config/bundles.php (Symfony 4).

  5. First Use Case: Sync Countries Run the sync command:

    php bin/console braune:geo:sync-countries
    

    Verify data in sonata_admin dashboard under "Countries" or "Cities".


Implementation Patterns

Workflow: Integrating Geo Data into Entities

  1. Entity Mapping Use the provided Country and City entities (or extend them):

    // src/Entity/YourEntity.php
    use BrauneDigital\GeoBundle\Entity\Country;
    
    /**
     * @ORM\ManyToOne(targetEntity="BrauneDigital\GeoBundle\Entity\Country")
     */
    private $country;
    
  2. Form Integration Use SonataAdmin’s built-in geo fields or create custom forms:

    // src/Admin/YourAdmin.php
    $formMapper
        ->add('country', 'sonata_type_model', [
            'model_manager' => $this->getModelManager(),
            'property' => 'country',
            'btn_add' => false,
        ]);
    
  3. API Data Fetching Leverage the bundle’s services to fetch geo data dynamically:

    // src/Service/GeoService.php
    use BrauneDigital\GeoBundle\Service\GeoService;
    
    public function __construct(private GeoService $geoService) {}
    
    public function getCitiesByCountryCode(string $countryCode): array {
        return $this->geoService->getCities($countryCode);
    }
    
  4. Translation Handling Use BrauneDigitalTranslationBaseBundle for multilingual support:

    # config/packages/braune_digital_translation.yaml
    braune_digital_translation:
        locales: [en, de, fr]
    
  5. Custom Actions in SonataAdmin Extend the admin class to add geo-specific actions:

    // src/Admin/CountryAdmin.php
    protected function configureListFields(ListMapper $listMapper) {
        $listMapper
            ->add('name')
            ->add('geonameId')
            ->add('_action', 'actions', [
                'actions' => [
                    'view' => [],
                    'edit' => [],
                    'delete' => [],
                    'sync' => ['template' => 'BrauneDigitalGeoBundle:Admin:sync.html.twig'],
                ],
            ]);
    }
    

Gotchas and Tips

Pitfalls

  1. API Rate Limits

    • Geonames.org has strict rate limits (e.g., 2000 requests/day for free accounts).
    • Cache responses aggressively:
      // src/Service/CachedGeoService.php
      use Symfony\Contracts\Cache\CacheInterface;
      
      public function getCities(string $countryCode) {
          return $this->cache->get("geonames_cities_{$countryCode}", function() use ($countryCode) {
              return $this->geoService->getCities($countryCode);
          }, 86400); // Cache for 1 day
      }
      
  2. Entity Overrides

    • Avoid directly modifying BrauneDigital\GeoBundle\Entity\Country or City. Instead, extend them:
      // src/Entity/Country.php
      use BrauneDigital\GeoBundle\Entity\Country as BaseCountry;
      
      class Country extends BaseCountry {
          // Add custom fields/methods
      }
      
    • Update sonata_easy_extends.yaml to point to your extended entities.
  3. SonataAdmin Caching Clear Sonata cache after syncing data:

    php bin/console sonata:cache:clear
    
  4. Doctrine Migrations

    • The bundle creates its own migrations. If you extend entities, generate custom migrations:
      php bin/console make:migration
      
  5. API Key Exposure

    • Never commit geonames_user to version control. Use environment variables:
      # .env
      GEONAMES_USER=your_username_here
      
      # config/packages/braune_digital_geo.yaml
      braune_digital_geo:
          geonames_user: '%env(GEONAMES_USER)%'
      

Debugging Tips

  1. Enable API Debugging Add a debug listener to log API calls:

    // src/EventListener/GeoDebugListener.php
    use BrauneDigital\GeoBundle\Service\GeoService;
    
    public function onKernelRequest(GetResponseEvent $event) {
        if ($event->isMainRequest()) {
            $this->geoService->setDebug(true);
        }
    }
    
  2. Check Sync Logs Run sync commands with verbose output:

    php bin/console braune:geo:sync-countries --verbose
    
  3. Validate Entities Use Symfony’s validator to ensure geo data integrity:

    // src/Validator/Constraints/CountryExists.php
    use Symfony\Component\Validator\Constraint;
    
    class CountryExists extends Constraint {
        public function validatedBy() { return static::class; }
    }
    

Extension Points

  1. Custom Geo Providers Override the default GeoService to use alternative providers (e.g., OpenStreetMap):

    // src/Service/CustomGeoService.php
    use BrauneDigital\GeoBundle\Service\GeoServiceInterface;
    
    class CustomGeoService implements GeoServiceInterface {
        public function getCountries(): array {
            // Implement custom logic
        }
    }
    

    Register as a service:

    # config/services.yaml
    BrauneDigital\GeoBundle\Service\GeoServiceInterface: '@App\Service\CustomGeoService'
    
  2. Custom Fields in SonataAdmin Add custom filters or fields using Sonata’s extension system:

    // src/Admin/Extension/CountryAdminExtension.php
    use Sonata\AdminBundle\Form\FormMapper;
    
    public function mapFormFields(FormMapper $formMapper) {
        $formMapper->add('isoCode', 'text', ['required' => false]);
    }
    
  3. Webhook for Syncs Trigger syncs via HTTP requests by creating a custom command:

    // src/Command/SyncGeoWebhookCommand.php
    use Symfony\Component\HttpKernel\Event\GetResponseEvent;
    
    public function onKernelRequest(GetResponseEvent $event) {
        if ($event->getRequest()->getPathInfo() === '/sync-geo') {
            $this->syncCountries();
            $event->setResponse(new Response('Synced!'));
        }
    }
    
  4. Bulk Operations Use Doctrine’s BulkOperations for large-scale updates:

    // src/Service/BulkGeoSyncService.php
    use Doctrine\ORM\EntityManagerInterface;
    
    public function bulkUpdateCountries(array $data) {
        $conn = $this->entityManager->getConnection();
        $conn->executeStatement('
            INSERT INTO country (geoname_id, name, iso_code)
            VALUES (:geoname_id, :name, :iso_code)
            ON CONFLICT (geoname_id) DO UPDATE SET name = EXCLUDED.name
        ', $data);
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui