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

Boxnow Bundle Laravel Package

answear/boxnow-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Use

  1. Install the Package

    composer require answear/boxnow-bundle
    

    Note: This package is Symfony-specific. For Laravel, you’ll need to manually adapt the logic (see Implementation Patterns).

  2. Configure BoxNow Credentials Create a Laravel-compatible config file at config/boxnow.php:

    return [
        'client_id' => env('BOXNOW_CLIENT_ID'),
        'client_secret' => env('BOXNOW_CLIENT_SECRET'),
        'api_url' => env('BOXNOW_API_URL', 'https://locationapi-stage.boxnow.gr'),
        'logger' => env('BOXNOW_LOGGER', null), // Optional: e.g., 'single', 'monolog'
    ];
    
  3. Set Up Environment Variables Add to .env:

    BOXNOW_CLIENT_ID=your_client_id
    BOXNOW_CLIENT_SECRET=your_client_secret
    
  4. Create a Service Provider Register the BoxNow services in app/Providers/BoxNowServiceProvider.php:

    namespace App\Providers;
    
    use Illuminate\Support\ServiceProvider;
    use Answear\BoxNowBundle\Service\AuthorizationService;
    use Answear\BoxNowBundle\Service\PickupPointService;
    
    class BoxNowServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(AuthorizationService::class, function ($app) {
                return new AuthorizationService(
                    config('boxnow.client_id'),
                    config('boxnow.client_secret'),
                    config('boxnow.api_url'),
                    $app->make('logger') ?? null
                );
            });
    
            $this->app->singleton(PickupPointService::class, function ($app) {
                return new PickupPointService(
                    $app->make('http.client'),
                    config('boxnow.api_url')
                );
            });
        }
    }
    

    Register the provider in config/app.php under providers.

  5. First Use Case: Fetch Pickup Points by Region

    use Answear\BoxNowBundle\Enum\RegionEnum;
    use Answear\BoxNowBundle\Service\PickupPointService;
    
    public function getCyprusPickupPoints(PickupPointService $pickupPoints)
    {
        $points = $pickupPoints->getAllByRegion(RegionEnum::Cyprus);
        return response()->json($points);
    }
    

    Note: RegionEnum must be adapted to Laravel’s enum or constants.


Implementation Patterns

Workflows

1. Authentication Flow

  • Symfony: Uses AuthorizationService with auto-injected dependencies.
  • Laravel Adaptation:
    public function authorize(AuthorizationService $authService)
    {
        $auth = $authService->authorize();
        $token = $auth->getAccessToken();
    
        // Store token for future requests (e.g., in cache or session)
        cache()->put('boxnow_token', $token, now()->addSeconds($auth->getExpiresIn()));
    
        return $token;
    }
    

2. Pickup Point Discovery

  • By Access Token:
    public function getPickupPointsByToken(PickupPointService $service)
    {
        $token = cache()->get('boxnow_token');
        $points = $service->getAll($token);
        return $points;
    }
    
  • By Region (e.g., Cyprus):
    public function getPickupPointsByRegion(PickupPointService $service)
    {
        $points = $service->getAllByRegion(RegionEnum::Cyprus);
        return $points;
    }
    

3. Error Handling

  • Wrap API calls in try-catch blocks to handle BoxNowApiException (adapted from Symfony’s ProblemDetails):
    try {
        $points = $service->getAll($token);
    } catch (\Answear\BoxNowBundle\Exception\BoxNowApiException $e) {
        Log::error('BoxNow API Error: ' . $e->getMessage());
        event(new BoxNowApiFailed($e));
        return response()->json(['error' => 'Failed to fetch pickup points'], 500);
    }
    

4. Caching Strategy

  • Cache pickup points for 1 hour to reduce API calls:
    public function getCachedPickupPoints(PickupPointService $service, RegionEnum $region)
    {
        $cacheKey = "boxnow_pickup_points_{$region->value}";
        return cache()->remember($cacheKey, now()->addHours(1), function () use ($service, $region) {
            return $service->getAllByRegion($region);
        });
    }
    

Integration Tips

  1. HTTP Client Configuration Configure Laravel’s HttpClient to match the bundle’s Guzzle settings (e.g., timeouts):

    $client = Http::withOptions([
        'timeout' => 30, // seconds
        'connect_timeout' => 10,
    ]);
    
  2. Region Enum Adaptation Replace Symfony’s RegionEnum with Laravel’s enum:

    namespace App\Enums;
    
    enum Region: string
    {
        case Greece = 'el-GR';
        case Cyprus = 'cy-CY';
        case Croatia = 'hr-HR';
        case Bulgaria = 'bg-BG';
    }
    
  3. Logging Use Laravel’s Log facade to replace Symfony’s Psr\Log\LoggerInterface:

    $logger = Log::channel('single'); // or 'monolog'
    
  4. Testing Mock the PickupPointService and AuthorizationService in Laravel tests:

    $mockService = Mockery::mock(PickupPointService::class);
    $mockService->shouldReceive('getAllByRegion')
                ->with(Region::Cyprus)
                ->andReturn([new PickupPointDTO()]);
    
    $this->app->instance(PickupPointService::class, $mockService);
    
  5. Event-Driven Extensions Dispatch events for critical actions (e.g., token refresh, API failures):

    class BoxNowTokenRefreshed implements ShouldBroadcast
    {
        public function __construct(public string $newToken) {}
    }
    
    // In AuthorizationService:
    event(new BoxNowTokenRefreshed($newToken));
    

Gotchas and Tips

Pitfalls

  1. Symfony-Specific Assumptions

    • Issue: The bundle assumes Symfony’s Serializer and PropertyInfo for DTO handling.
    • Fix: Replace with Laravel’s collect() or json_decode():
      // Symfony (original):
      $serializer = $this->serializer->serialize($data, 'json');
      
      // Laravel adaptation:
      $data = json_decode($response->body(), true);
      
  2. Region Enum Mismatch

    • Issue: RegionEnum uses Symfony’s Enum trait, which isn’t native to Laravel.
    • Fix: Use Laravel’s enum or a simple class:
      class Region
      {
          const GREECE = 'el-GR';
          const CYPRUS = 'cy-CY';
      }
      
  3. Authentication Token Management

    • Issue: The bundle doesn’t persist tokens between requests.
    • Fix: Cache the token or use Laravel’s Auth session driver:
      $token = cache()->remember('boxnow_token', now()->addMinutes(50), function () {
          return $authService->authorize()->getAccessToken();
      });
      
  4. Guzzle vs. Laravel HttpClient

    • Issue: The bundle uses Guzzle directly, which may conflict with Laravel’s HttpClient.
    • Fix: Inject Laravel’s HttpClient into services:
      public function __construct(private HttpClient $http) {}
      
  5. Logger Dependency

    • Issue: The bundle expects Psr\Log\LoggerInterface, but Laravel’s Log facade isn’t a direct drop-in.
    • Fix: Create a wrapper:
      class LaravelLogger implements LoggerInterface
      {
          public function __construct(private \Illuminate\Log\Logger $logger) {}
      
          public function error(string $message, array $context = []): void
          {
              $this->logger->error($message, $context);
          }
          // Implement other Psr\Log methods...
      }
      

Debugging Tips

  1. Enable API Logging Add debug logging to track API calls:

    $this->logger->debug('BoxNow API Request', [
        'url' => $url,
        'data' => $data,
        'headers' => $headers,
    ]);
    
  2. Validate API Responses Use Laravel’s Http facade to inspect raw responses:

    $response = Http::withHeaders(['Authorization' => '
    
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.
phalcon/cli-options-parser
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi