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

Channel Laravel Package

sylius/channel

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require sylius/channel
    

    Add the bundle to config/bundles.php (if using Symfony) or register the component in your Laravel service provider.

  2. Configuration: Define channels in config/channel.php (or equivalent):

    'channels' => [
        'web' => [
            'name' => 'Main Website',
            'code' => 'WEB',
            'enabled' => true,
            'prices' => ['USD', 'EUR'],
            'currencies' => ['USD', 'EUR'],
            'locales' => ['en_US', 'fr_FR'],
            'tax_categories' => ['standard', 'reduced'],
        ],
    ],
    
  3. First Use Case: Fetch a channel by code in a controller:

    use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
    
    public function show(ChannelRepositoryInterface $channelRepository)
    {
        $channel = $channelRepository->findOneBy(['code' => 'WEB']);
        return view('channel.show', ['channel' => $channel]);
    }
    

Key Classes to Explore

  • Channel (entity representing a sales channel)
  • ChannelRepository (for fetching channels)
  • ChannelContext (for context-aware operations)
  • ChannelAwareInterface (for entities that need channel context)

Implementation Patterns

Core Workflows

1. Channel-Aware Entities

Extend or implement ChannelAwareInterface for entities like products, taxes, or promotions:

use Sylius\Component\Channel\ChannelAwareInterface;

class Product implements ChannelAwareInterface
{
    private ?ChannelInterface $channel = null;

    public function getChannel(): ?ChannelInterface
    {
        return $this->channel;
    }

    public function setChannel(?ChannelInterface $channel): void
    {
        $this->channel = $channel;
    }
}

2. Contextual Operations

Use ChannelContext to resolve the current channel (e.g., from request or session):

use Sylius\Component\Channel\Context\ChannelContextInterface;

public function getCurrentChannel(ChannelContextInterface $channelContext)
{
    return $channelContext->getChannel();
}

3. Channel-Specific Data

Store channel-specific configurations in a ChannelPricing or ChannelTaxation entity:

use Sylius\Component\Channel\ChannelInterface;

class ProductPricing
{
    private ChannelInterface $channel;
    private float $price;

    // Getters/setters...
}

4. API/Route Scoping

Filter resources by channel in API routes or queries:

// Example: API route for channel-specific products
Route::get('/channels/{code}/products', [ProductController::class, 'index'])
    ->where('code', '[A-Za-z0-9_-]+');

5. Event-Driven Extensions

Listen for ChannelCreatedEvent or ChannelUpdatedEvent to trigger side effects:

use Sylius\Component\Channel\Event\ChannelCreatedEvent;

public function onChannelCreated(ChannelCreatedEvent $event)
{
    // Sync channel with external services, e.g., CDN or analytics
}

Integration Tips

Laravel-Specific Patterns

  1. Service Provider Binding: Bind the repository and context in AppServiceProvider:

    public function register()
    {
        $this->app->bind(ChannelRepositoryInterface::class, function ($app) {
            return new ChannelRepository($app->make(EntityManagerInterface::class]);
        });
    }
    
  2. Request-Based Channel Resolution: Resolve the channel from the request in middleware:

    public function handle(Request $request, Closure $next)
    {
        $channelCode = $request->get('channel', config('channel.default'));
        $channel = app(ChannelRepositoryInterface::class)->findOneBy(['code' => $channelCode]);
        app(ChannelContextInterface::class)->setChannel($channel);
        return $next($request);
    }
    
  3. Eloquent Model Extensions: Add channel-aware behavior to Eloquent models:

    use Sylius\Component\Channel\ChannelAwareInterface;
    
    class Product extends Model implements ChannelAwareInterface
    {
        use ChannelAwareTrait; // Hypothetical trait for Sylius-style channel handling
    }
    
  4. Caching Channel Data: Cache channel configurations to avoid repeated DB lookups:

    $channel = Cache::remember("channel:{$code}", now()->addHours(1), function () use ($code) {
        return $channelRepository->findOneBy(['code' => $code]);
    });
    

Gotchas and Tips

Pitfalls

  1. Channel Context Leaks:

    • Issue: Forgetting to set the ChannelContext before accessing channel-aware entities.
    • Fix: Use middleware to ensure the context is set early in the request lifecycle.
    • Debug: Check for NullChannelException if a channel-aware entity lacks context.
  2. Overlapping Channel Configurations:

    • Issue: Conflicting configurations (e.g., same currency in multiple channels).
    • Fix: Validate channel configurations during creation/updates:
      $channel->validate(); // If using Sylius' validation
      
  3. Performance with N+1 Queries:

    • Issue: Eager-loading channel-aware entities without relations.
    • Fix: Use with() in queries or DTOs to preload channel data:
      $products = Product::with(['channel', 'prices.channel'])->get();
      
  4. Locale/Currency Mismatches:

    • Issue: Channel locales/currencies not aligned with actual data.
    • Fix: Add validation in Channel entity or use a ChannelValidator:
      $channel->getLocales()->mustBeSubsetOf(app()->getLocales());
      
  5. Hardcoded Channel Codes:

    • Issue: Magic strings for channel codes (e.g., 'WEB').
    • Fix: Use constants or enums:
      final class ChannelCodes
      {
          public const WEB = 'WEB';
          public const MOBILE = 'MOBILE';
      }
      

Debugging Tips

  1. Log Channel Context: Add a debug middleware to log the current channel:

    public function handle($request, Closure $next)
    {
        \Log::debug('Current channel:', [
            'code' => app(ChannelContextInterface::class)->getChannel()?->getCode(),
        ]);
        return $next($request);
    }
    
  2. Validate Channel Entities: Use Sylius' validation or custom rules to catch issues early:

    $validator = Validator::make($channelData, [
        'code' => 'required|unique:channels|size:3',
        'locales' => 'array|min:1',
    ]);
    
  3. Test Channel Isolation: Write tests to ensure channel-specific logic works in isolation:

    public function test_channel_specific_pricing()
    {
        $channel = $this->createChannel(['code' => 'WEB']);
        $product = $this->createProduct(['channel' => $channel]);
        $this->assertEquals(19.99, $product->getPrice()->getAmount());
    }
    

Extension Points

  1. Custom Channel Types: Extend the Channel entity to add custom fields:

    class CustomChannel extends Channel
    {
        private ?string $theme = null;
    
        // Add getters/setters and DB mapping
    }
    
  2. Dynamic Channel Routing: Use a router to dynamically generate channel-specific routes:

    Route::prefix('{channel_code}')->group(function () {
        Route::get('/products', [ProductController::class, 'index']);
    });
    
  3. Channel-Specific Middleware: Apply middleware based on the current channel:

    $channel = app(ChannelContextInterface::class)->getChannel();
    if ($channel->getCode() === 'MOBILE') {
        $request->headers->set('X-Channel', 'MOBILE');
    }
    
  4. Event Subscribers: Subscribe to channel events for cross-cutting concerns:

    use Sylius\Component\Channel\Event\ChannelCreatedEvent;
    
    public static function getSubscribedEvents()
    {
        return [
            ChannelCreatedEvent::class => 'onChannelCreated',
        ];
    }
    
  5. API Resource Transformers: Use Fractal or similar to transform channel-aware entities:

    $transformer = new ProductTransformer();
    $resource = $transformer->transform($product, (new Data::class)->withChannel());
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor