Installation:
composer require baks-dev/moysklad
php bin/console baks:assets:install
baks:assets:install (checks for config/packages/baks_dev_moysklad.yaml and migrations/).Configuration:
php bin/console config:dump-reference baks_dev_moysklad
config/packages/baks_dev_moysklad.yaml with your Moysklad API credentials (client_id, client_secret, token, company_id).First Use Case:
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());
CRUD 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);
Bulk Operations:
bulkSave() for batch inserts/updates:
$offers = [
(new Offer())->setName('Product A'),
(new Offer())->setName('Product B'),
];
$client->getOfferRepository()->bulkSave($offers);
Event-Driven Sync:
moysklad.yaml):
moysklad:
webhooks:
enabled: true
endpoint: '/moysklad/webhook'
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']);
}
}
Custom Fields:
use BaksDev\Moysklad\Entity\Offer;
use Doctrine\Common\Collections\ArrayCollection;
$offer = new Offer();
$offer->setCustomFields(new ArrayCollection([
['name' => 'custom_field', 'value' => 'value123'],
]));
Dependency Injection:
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']
);
});
Caching:
CacheAdapter):
moysklad:
repositories:
offer:
cache_enabled: true
cache_ttl: 3600 # 1 hour
Logging:
moysklad:
debug: true
Testing:
$mockClient = $this->createMock(MoyskladClient::class);
$mockClient->method('getOfferRepository')
->willReturn($this->createMock(OfferRepository::class));
$this->app->instance(MoyskladClient::class, $mockClient);
Authentication:
401 Unauthorized by refreshing the token:
try {
$client->getOfferRepository()->find(123);
} catch (AuthenticationException $e) {
$client->refreshToken(); // Implement this method
retry();
}
use Symfony\Component\HttpClient\RetryableHttpClient;
$client = new MoyskladClient();
$httpClient = new RetryableHttpClient(
$client->getHttpClient(),
['max_retries' => 3, 'delay' => 1000]
);
$client->setHttpClient($httpClient);
Data Mismatches:
if (!isset($response['id'])) {
throw new \RuntimeException('Unexpected API response format');
}
Webhooks:
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);
}
}
Entity Hydration:
N+1 queries by eager-loading associations:
$offer = $client->getOfferRepository()
->find(123, ['attributes' => ['images', 'custom_fields']]);
Enable Debug Mode:
moysklad:
debug: true
var/log/moysklad.log.Raw API Calls:
$response = $client->getHttpClient()->request('GET', '/api/remap/1.2/entity/offer/123');
dd($response->getContent());
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.Custom Entities:
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;
}
}
Repository Decorators:
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'
Event Subscribers:
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());
}
}
}
How can I help you explore Laravel packages today?