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

Multi Domain Bundle Laravel Package

appventus/multi-domain-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add the package via Composer:

    composer require appventus/multi-domain-bundle:dev-master
    

    Register the bundle in config/bundles.php:

    return [
        // ...
        AppVentus\MultiDomainBundle\AvMultiDomainBundle::class => ['all' => true],
    ];
    
  2. Entity Integration Add the DomainTrait to any entity you want to restrict by domain (e.g., Page):

    use AppVentus\MultiDomainBundle\Traits\DomainTrait;
    
    /**
     * @ORM\Entity
     */
    class Page
    {
        use DomainTrait;
    
        // ...
    }
    
  3. First Use Case

    • Ensure your entity has a domain field (auto-added by the trait).
    • Access entities via a domain-specific route (e.g., app.example.com/pages/1).
    • The bundle automatically filters queries to only return records matching the current request domain.

Implementation Patterns

Domain-Aware Routing

  • Route Annotations: Use Symfony’s routing with domain constraints:

    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Domain;
    
    /**
     * @Route("/pages/{id}", name="page_show")
     * @Domain("example.com")
     */
    public function showPage(Page $page) { ... }
    

    Note: The bundle doesn’t enforce this natively; combine with stof/doctrine-extensions-bundle for @Domain support.

  • Dynamic Domain Resolution: Override the default domain resolver (e.g., in a custom DomainResolver service) to fetch domains from a database or API:

    // config/services.yaml
    AppVentus\MultiDomainBundle\DomainResolverInterface: '@app.custom_domain_resolver'
    

Query Filtering

  • Repository Methods: Extend entity repositories to leverage domain filtering:

    class PageRepository extends ServiceEntityRepository
    {
        public function findByDomain(string $domain): array
        {
            return $this->createQueryBuilder('p')
                ->andWhere('p.domain = :domain')
                ->setParameter('domain', $domain)
                ->getQuery()
                ->getResult();
        }
    }
    
  • Event Listeners: Attach listeners to filter collections globally (e.g., in PageRepository):

    use AppVentus\MultiDomainBundle\EventListener\DomainFilterListener;
    
    // config/services.yaml
    AppVentus\MultiDomainBundle\EventListener\DomainFilterListener:
        tags:
            - { name: doctrine.event_listener, event: onFind }
    

Multi-Tenant Workflows

  • Database Connections: Combine with doctrine/dbal to switch databases per domain:

    // Custom DomainResolver
    public function getDomain(): string
    {
        $domain = parent::getDomain();
        $connection = $this->connectionManager->getConnectionForDomain($domain);
        // ...
    }
    
  • Shared vs. Isolated Data:

    • Use DomainTrait for shared data (e.g., global settings).
    • For isolated data (e.g., user profiles), add a tenant_id field and filter manually.

Gotchas and Tips

Pitfalls

  1. Missing Domain Field: The trait adds a domain field automatically, but ensure your database schema includes it:

    php bin/console doctrine:schema:update --force
    
  2. Case Sensitivity: Domains are case-sensitive by default. Normalize them in the resolver:

    return strtolower($request->getHost());
    
  3. Caching Issues: Doctrine’s second-level cache may serve stale domain-filtered results. Exclude cached queries:

    ->useResultCache(false)
    ->useQueryCache(false)
    
  4. Subdomains vs. Domains: The bundle treats app.example.com and example.com as distinct. Use regex in the resolver if needed:

    if (preg_match('/^(app\.)?example\.com$/', $host)) { ... }
    

Debugging

  • Check Current Domain: Inject DomainResolverInterface into controllers to debug:

    public function index(DomainResolverInterface $resolver)
    {
        dump($resolver->getDomain()); // e.g., "example.com"
    }
    
  • Query Logs: Enable Doctrine logging to verify filters:

    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            logging: true
            profiling: true
    

Extension Points

  1. Custom Domain Sources: Override DomainResolverInterface to fetch domains from a custom source (e.g., Redis):

    class RedisDomainResolver implements DomainResolverInterface
    {
        public function getDomain(): string
        {
            return $this->redis->get('current_domain');
        }
    }
    
  2. Dynamic Entity Filtering: Extend the DomainTrait to support multi-domain entities:

    trait MultiDomainTrait extends DomainTrait
    {
        public function isDomainMatch(string $domain): bool
        {
            return in_array($domain, $this->domains);
        }
    }
    
  3. Fallback Domains: Configure a fallback domain in config/packages/av_multi_domain.yaml:

    av_multi_domain:
        fallback_domain: "default.example.com"
    

Performance Tips

  • Index the Domain Field: Add a database index to speed up queries:

    /**
     * @ORM\Table(indexes={@ORM\Index(name="idx_domain", columns={"domain"})})
     */
    class Page { ... }
    
  • Batch Domain Updates: Use Doctrine’s bulk operations for mass domain assignments:

    $em->createQueryBuilder()
        ->update(Page::class, 'p')
        ->set('p.domain', ':domain')
        ->where('p.domain IS NULL')
        ->setParameter('domain', 'example.com')
        ->getQuery()
        ->execute();
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware