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

Artful Laravel Package

yansongda/artful

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:
    composer require yansongda/artful:~1.1.0
    
  2. Basic Configuration (config/artful.php):
    return [
        'http' => [
            'timeout' => 30.0,
            'base_uri' => 'https://api.example.com',
        ],
        'clients' => [
            'default' => [
                'plugins' => [],
            ],
        ],
    ];
    
  3. First Request (Laravel Service Provider):
    use Yansongda\Artful\Artful;
    use Yansongda\Artful\ArtfulManager;
    
    public function register()
    {
        $this->app->singleton(ArtfulManager::class, function ($app) {
            return new ArtfulManager($app['config']['artful']);
        });
    }
    
    public function boot()
    {
        $response = Artful::client('default')->get('/users');
        $data = $response->toArray();
    }
    

First Use Case: Third-Party API Integration

Replace a Guzzle-based payment gateway call:

// Before (Guzzle)
$client = new \GuzzleHttp\Client();
$response = $client->post('https://api.stripe.com/payments', [
    'json' => ['amount' => 100],
    'headers' => ['Authorization' => 'Bearer ' . $token],
]);

// After (Artful)
$response = Artful::client('stripe')->post('/payments', [
    'json' => ['amount' => 100],
]);

Implementation Patterns

1. Modular API Clients

Pattern: One file per API service with isolated configurations.

// config/artful.php
return [
    'clients' => [
        'stripe' => [
            'base_uri' => 'https://api.stripe.com/v1',
            'plugins' => [
                \Yansongda\Artful\Plugin\AuthPlugin::class,
            ],
            'auth' => [
                'type' => 'bearer',
                'token' => env('STRIPE_TOKEN'),
            ],
        ],
        'shopify' => [
            'base_uri' => 'https://{shop}.myshopify.com/admin/api/2023-07',
            'plugins' => [
                \App\Plugins\ShopifyHeaderPlugin::class,
            ],
        ],
    ],
];

2. Plugin-Based Workflows

Pattern: Extend functionality without modifying core logic.

// app/Plugins/CustomHeaderPlugin.php
namespace App\Plugins;

use Yansongda\Artful\Plugin\AbstractPlugin;
use Psr\Http\Message\RequestInterface;

class CustomHeaderPlugin extends AbstractPlugin
{
    public function handle(RequestInterface $request)
    {
        return $request->withHeader('X-Custom-Header', 'value');
    }
}

// Usage in config/artful.php
'clients' => [
    'analytics' => [
        'plugins' => [
            \App\Plugins\CustomHeaderPlugin::class,
        ],
    ],
],

3. Event-Driven Hooks

Pattern: Trigger actions on request/response lifecycle.

// Listen to response events
Artful::event()->listen(\Yansongda\Artful\Event\RequestStarted::class, function ($event) {
    \Log::info('API request started', ['url' => $event->getRequest()->getUri()]);
});

// Listen to response events
Artful::event()->listen(\Yansongda\Artful\Event\ResponseReceived::class, function ($event) {
    if ($event->getResponse()->getStatusCode() >= 400) {
        \Log::error('API request failed', [
            'status' => $event->getResponse()->getStatusCode(),
            'body' => $event->getResponse()->getBody(),
        ]);
    }
});

4. Swoole Async Requests

Pattern: Non-blocking API calls for high-performance scenarios.

// Enable Swoole in config/artful.php
'http' => [
    'factory' => \Yansongda\Artful\SwooleHttpFactory::class,
],

// Async request
$response = Artful::client('swoole')->getAsync('/data')->wait();

5. Laravel Integration

Pattern: Bind Artful to Laravel’s service container.

// app/Providers/ArtfulServiceProvider.php
public function register()
{
    $this->app->singleton(\Yansongda\Artful\ArtfulManager::class, function ($app) {
        $manager = new ArtfulManager($app['config']['artful']);
        $manager->setEventDispatcher($app->make(\Yansongda\Artful\Event\EventDispatcher::class));
        return $manager;
    });

    $this->app->alias(\Yansongda\Artful\Artful::class, \Yansongda\Artful\ArtfulManager::class);
}

6. Dynamic Configuration

Pattern: Override configurations per request.

$response = Artful::client('default')
    ->withConfig(['timeout' => 60.0])
    ->get('/slow-endpoint');

Gotchas and Tips

Pitfalls

  1. Config Key Changes:

    • Issue: httpFactory was renamed to http in v1.1.0.
    • Fix: Update config/artful.php if upgrading from older versions.
      // Old (v1.0.x)
      'httpFactory' => \Yansongda\Artful\Http\GuzzleHttpFactory::class,
      
      // New (v1.1.0+)
      'http' => \Yansongda\Artful\Http\GuzzleHttpFactory::class,
      
  2. Plugin Execution Order:

    • Issue: Plugins run in the order they’re defined, but some may override others unintentionally.
    • Fix: Use Plugin\PriorityPlugin to enforce execution order.
      'plugins' => [
          \App\Plugins\AuthPlugin::class,
          \App\Plugins\LoggingPlugin::class,
      ],
      
  3. Swoole Compatibility:

    • Issue: Swoole may conflict with Laravel’s default event loop or queue workers.
    • Fix: Test in a staging environment and isolate Swoole-based clients.
      // Disable Swoole for specific clients
      'clients' => [
          'swoole_client' => [
              'http' => \Yansongda\Artful\Http\GuzzleHttpFactory::class, // Force Guzzle
          ],
      ],
      
  4. PSR-7 Message Handling:

    • Issue: Artful uses PSR-7 messages, which may differ from Laravel’s Illuminate\Http\Request.
    • Fix: Convert between formats explicitly:
      $psr7Request = Artful::client()->createRequest('GET', '/users');
      $laravelRequest = new \Illuminate\Http\Request(
          $psr7Request->getMethod(),
          $psr7Request->getUri(),
          $psr7Request->getHeaders(),
          [],
          [],
          $psr7Request->getBody()
      );
      
  5. Event Dispatcher Conflicts:

    • Issue: Artful’s event dispatcher may conflict with Laravel’s if not properly bridged.
    • Fix: Use a custom event dispatcher that delegates to Laravel’s:
      $dispatcher = new \Yansongda\Artful\Event\LaravelEventDispatcher($this->app['events']);
      Artful::event()->setDispatcher($dispatcher);
      
  6. Empty Packer Handling:

    • Issue: JsonPacker may throw errors if no packer is set.
    • Fix: Ensure config/artful.php includes a default packer:
      'packer' => \Yansongda\Artful\Packer\JsonPacker::class,
      

Debugging Tips

  1. Enable Verbose Logging:

    Artful::client()->setDebug(true);
    

    Check logs for raw request/response details.

  2. Inspect Plugins: Use Artful::client()->getPlugins() to list active plugins and their order.

  3. Mock HTTP Calls: Replace the HTTP factory in tests:

    $manager = new ArtfulManager($config);
    $manager->setHttpFactory(new \Yansongda\Artful\Http\MockHttpFactory());
    
  4. Validate PSR Compliance: Use phpstan to ensure PSR-7/11 compliance:

    composer require --dev phpstan/phpstan
    vendor/bin/phpstan analyse --level=5
    

Extension Points

  1. Custom HTTP Factory: Implement Yansongda\Artful\Http\HttpFactoryInterface for non-Guzzle/Swoole clients (e.g., cURL).
    class CustomHttpFactory implements HttpFactoryInterface
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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