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

Moysklad Laravel Package

baks-dev/moysklad

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require baks-dev/moysklad
    php bin/console baks:assets:install
    
    • Runs migrations automatically via baks:assets:install (checks for config/packages/baks_dev_moysklad.yaml and migrations/).
  2. Configuration:

    • Publish the default config:
      php bin/console config:dump-reference baks_dev_moysklad
      
    • Update config/packages/baks_dev_moysklad.yaml with your Moysklad API credentials (client_id, client_secret, token, company_id).
  3. First Use Case:

    • Fetch a single entity (e.g., an offer):
      use BaksDev\Moysklad\Client\MoyskladClient;
      use BaksDev\Moysklad\Entity\Offer;
      
      $client = new MoyskladClient();
      $offer = $client->getOfferRepository()->find(123); // Replace 123 with an actual ID
      dd($offer->getName());
      

Implementation Patterns

Core Workflows

  1. CRUD Operations:

    • Use repository methods for standard operations:
      // Create
      $offer = new Offer();
      $offer->setName('New Product');
      $client->getOfferRepository()->save($offer);
      
      // Update
      $offer->setPrice(1000.50);
      $client->getOfferRepository()->save($offer);
      
      // Delete
      $client->getOfferRepository()->remove($offer);
      
  2. Bulk Operations:

    • Use bulkSave() for batch inserts/updates:
      $offers = [
          (new Offer())->setName('Product A'),
          (new Offer())->setName('Product B'),
      ];
      $client->getOfferRepository()->bulkSave($offers);
      
  3. Event-Driven Sync:

    • Listen to Moysklad webhooks (configured in moysklad.yaml):
      moysklad:
          webhooks:
              enabled: true
              endpoint: '/moysklad/webhook'
      
    • Handle updates in a controller:
      public function handleWebhook(Request $request, MoyskladClient $client)
      {
          $payload = json_decode($request->getContent(), true);
          $event = $payload['event'];
          $entity = $payload['entity'];
      
          if ($event === 'offer.update') {
              $client->getOfferRepository()->refresh($entity['id']);
          }
      }
      
  4. Custom Fields:

    • Extend entities with custom attributes:
      use BaksDev\Moysklad\Entity\Offer;
      use Doctrine\Common\Collections\ArrayCollection;
      
      $offer = new Offer();
      $offer->setCustomFields(new ArrayCollection([
          ['name' => 'custom_field', 'value' => 'value123'],
      ]));
      

Integration Tips

  1. Dependency Injection:

    • Bind MoyskladClient in a service provider:
      $this->app->bind(MoyskladClient::class, function ($app) {
          return new MoyskladClient(
              $app['config']['moysklad.client_id'],
              $app['config']['moysklad.client_secret'],
              $app['config']['moysklad.token']
          );
      });
      
  2. Caching:

    • Enable caching for repositories (e.g., CacheAdapter):
      moysklad:
          repositories:
              offer:
                  cache_enabled: true
                  cache_ttl: 3600 # 1 hour
      
  3. Logging:

    • Enable debug logs for API calls:
      moysklad:
          debug: true
      
  4. Testing:

    • Mock the client in unit tests:
      $mockClient = $this->createMock(MoyskladClient::class);
      $mockClient->method('getOfferRepository')
          ->willReturn($this->createMock(OfferRepository::class));
      $this->app->instance(MoyskladClient::class, $mockClient);
      

Gotchas and Tips

Pitfalls

  1. Authentication:

    • Token Expiry: Moysklad tokens expire. Handle 401 Unauthorized by refreshing the token:
      try {
          $client->getOfferRepository()->find(123);
      } catch (AuthenticationException $e) {
          $client->refreshToken(); // Implement this method
          retry();
      }
      
    • Rate Limits: Moysklad enforces rate limits. Use exponential backoff for retries:
      use Symfony\Component\HttpClient\RetryableHttpClient;
      
      $client = new MoyskladClient();
      $httpClient = new RetryableHttpClient(
          $client->getHttpClient(),
          ['max_retries' => 3, 'delay' => 1000]
      );
      $client->setHttpClient($httpClient);
      
  2. Data Mismatches:

    • Schema Changes: Moysklad’s API evolves. Validate responses against the official API docs:
      if (!isset($response['id'])) {
          throw new \RuntimeException('Unexpected API response format');
      }
      
  3. Webhooks:

    • Signature Verification: Always verify webhook signatures:
      public function handleWebhook(Request $request)
      {
          $signature = $request->headers->get('X-Moysklad-Signature');
          $expectedSignature = hash_hmac(
              'sha256',
              $request->getContent(),
              config('moysklad.webhook_secret')
          );
          if (!hash_equals($signature, $expectedSignature)) {
              abort(403);
          }
      }
      
  4. Entity Hydration:

    • Lazy Loading: Avoid N+1 queries by eager-loading associations:
      $offer = $client->getOfferRepository()
          ->find(123, ['attributes' => ['images', 'custom_fields']]);
      

Debugging Tips

  1. Enable Debug Mode:

    moysklad:
        debug: true
    
    • Logs API requests/responses to var/log/moysklad.log.
  2. Raw API Calls:

    • Bypass the client for direct debugging:
      $response = $client->getHttpClient()->request('GET', '/api/remap/1.2/entity/offer/123');
      dd($response->getContent());
      
  3. Common Errors:

    • 404 Not Found: Verify company_id and entity IDs.
    • 400 Bad Request: Check required fields (e.g., name for offer).
    • 500 Internal Server Error: Contact Moysklad support or check their status page.

Extension Points

  1. Custom Entities:

    • Extend base entities (e.g., Offer) for domain-specific logic:
      namespace App\Entity;
      
      use BaksDev\Moysklad\Entity\Offer as BaseOffer;
      
      class Offer extends BaseOffer
      {
          public function isPremium(): bool
          {
              return $this->getPrice() > 1000;
          }
      }
      
  2. Repository Decorators:

    • Override repository methods:
      use BaksDev\Moysklad\Repository\OfferRepository;
      
      class CustomOfferRepository extends OfferRepository
      {
          public function findWithStock($id)
          {
              $offer = parent::find($id);
              $offer->setStock($this->getStockService()->getStock($offer->getId()));
              return $offer;
          }
      }
      
      Register in services.yaml:
      services:
          BaksDev\Moysklad\Repository\OfferRepository: '@App\Repository\CustomOfferRepository'
      
  3. Event Subscribers:

    • Listen to entity events (e.g., preSave):
      use BaksDev\Moysklad\Event\PreSaveEvent;
      use Symfony\Component\EventDispatcher\EventSubscriberInterface;
      
      class OfferSubscriber implements EventSubscriberInterface
      {
          public static function getSubscribedEvents()
          {
              return [
                  PreSaveEvent::class => 'onPreSave',
              ];
          }
      
          public function onPreSave(PreSaveEvent $event)
          {
              if ($event->getEntity() instanceof Offer) {
                  $event->getEntity()->setUpdatedAt(new \DateTime());
              }
          }
      }
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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