baks-dev/wildberries-package
baks-dev/wildberries-package — PHP 8.4+ модуль упаковки заказов Wildberries. Установка через Composer, установка конфигурации и ресурсов командой baks:assets:install, миграции Doctrine, тесты PHPUnit. Подходит для интеграции обработки и упаковки заказов в проект.
Reality check before you type composer require: despite being pitched as a Laravel module, everything in this package's README is Symfony/BaksDev convention — php bin/console, baks:assets:install, doctrine:migrations:diff, doctrine:migrations:migrate. There is no WildberriesServiceProvider, no config/wildberries.php publish tag, no Artisan commands documented. Treat it as a domain/schema accelerator you source-inspect and adapt, not a package you require into a Laravel app and expect to work.
Prerequisites
Minimal first steps (do these in a scratch app, not your main repo)
# 1. Pin exactly — releases are version-only, so "latest" is a coin flip
composer require baks-dev/wildberries-package:7.4.36
# 2. Read the source before running anything
cat vendor/baks-dev/wildberries-package/composer.json
ls vendor/baks-dev/wildberries-package/src
ls vendor/baks-dev/wildberries-package/src/Resources/config 2>/dev/null
ls vendor/baks-dev/wildberries-package/migrations 2>/dev/null
Where to look first, in order
composer.json → does it declare type: symfony-bundle, a Bundles entry, or a Laravel extra.laravel.providers? This single file tells you whether a Laravel integration even exists.src/Entity (or src/Domain) → the actual packaging/assembly-task model. This is the only thing you're really buying.wildberries_*?), column types, FKs, indexes.phpunit.xml + test group → what --group=wildberries-package actually asserts.CHANGELOG.md → you'll find it's version stubs, which is your signal on maintenance risk.Your first real use case: don't build a feature. Build a schema diff you can read:
# in a Symfony-shaped scratch container with Doctrine migrations installed
php bin/console doctrine:migrations:diff
# then READ the generated SQL, do not migrate
That diff is the deliverable of day one. It answers the only questions that matter: what tables appear, what they FK to, whether they collide with your orders/shipments, and whether IDs are compatible. From that diff you decide: bridge Doctrine, or reimplement as Eloquent migrations.
Then wire up one read-only path in Laravel — a single GET /wildberries/packaging-tasks endpoint backed by a repository that reads the new tables — and prove data flows before writing anything.
Never let package classes leak into controllers, jobs, or Blade. One internal interface, one implementation, swapped later if you fork or reimplement.
namespace App\Wildberries\Contracts;
interface PackagingTaskRepository
{
/** @return PackagingTask[] */
public function pendingForWarehouse(string $warehouseId, int $limit = 100): array;
public function markAssembled(string $taskId, string $actorId): void;
}
Bind it in AppServiceProvider:
$this->app->bind(
\App\Wildberries\Contracts\PackagingTaskRepository::class,
\App\Wildberries\Doctrine\DoctrinePackagingTaskRepository::class
);
The interface is your escape hatch. If the package dies upstream (0 stars, 0 dependents — assume it might), you swap the binding and nothing else moves.
Laravel ships Eloquent; the package assumes Doctrine ORM/DBAL/Migrations. Bridging means adding doctrine/dbal + an EntityManager, which is real weight. Two viable shapes:
2a. Shared connection, separate EntityManager — reuse your existing Laravel DB credentials so package entities and Eloquent models see the same rows in the same transaction.
// config/doctrine.php — minimal, one connection, entity paths pointing at the package
'managers' => [
'wildberries' => [
'connection' => 'mysql', // reuse Laravel's connection
'paths' => [base_path('vendor/baks-dev/wildberries-package/src/Entity')],
'is_dev_mode' => false,
],
],
Wrap cross-cutting writes in a single transaction so an Eloquent Order update and a Doctrine PackagingTask insert commit together — otherwise you get status drift between the two ORMs.
2b. Schema port to Eloquent (usually the better call)
Take the SQL from doctrine:migrations:diff, hand-write Laravel migrations against it, and recreate the entities as Eloquent models. More upfront typing, zero Doctrine runtime, no dual-ORM transaction hazards, and your team can debug it. For a module this narrow ("упаковка заказов" — order packaging), the entity count is small.
// database/migrations/xxxx_create_wildberries_packaging_tasks.php
Schema::create('wildberries_packaging_tasks', function (Blueprint $t) {
$t->uuid('id')->primary();
$t->foreignUuid('order_id')->constrained('orders'); // verify FK target in the diff first
$t->string('warehouse_id')->index();
$t->string('status')->index();
$t->timestamp('assembled_at')->nullable();
$t->timestamps();
});
Do not blindly replay package SQL: check the FK target table name, ID type (UUID vs BIGINT), and whether indexes overlap ones you already have.
baks:assets:install into Laravel publishingThe Symfony command copies config/assets into the app. In Laravel, do it manually and commit the result so upgrades are reviewable:
cp -r vendor/baks-dev/wildberries-package/src/Resources/config config/wildberries.php
Then read the file and replace anything package-internal with env()-driven values (currency, warehouse defaults, statuses). Keep the original in vendor/ untouched — that's your diff baseline on upgrade.
doctrine:migrations:* against your app DBIf you keep Doctrine for schema, isolate it:
DB::unprepared() of reviewed SQL, and always write a down().public function up(): void
{
DB::unprepared(file_get_contents(database_path('sql/wildberries_v7436_up.sql')));
}
public function down(): void
{
DB::unprepared(file_get_contents(database_path('sql/wildberries_v7436_down.sql')));
}
Packaging is batch work (pick list → assemble → label). Never do it in a request.
class AssemblePackagingTasks implements ShouldQueue
{
use Queueable, Batchable;
public function __construct(
public string $warehouseId,
public array $taskIds,
) {}
public function handle(PackagingTaskRepository $tasks): void
{
foreach ($this->taskIds as $id) {
$tasks->markAssembled($id, 'system');
}
}
}
If you go the Doctrine route, call $em->clear() between chunks — long-running workers leak managed entities and eventually blow memory. That's a Doctrine-specific footgun Eloquent devs won't expect.
Adoption is zero. Ship behind a flag and a warehouse allowlist so a bad migration or a mis-modelled task can be switched off without a rollback deploy:
if (! Feature::active('wildberries.packaging')) {
return;
}
The package's group is Symfony PHPUnit (php bin/phpunit --group=wildberries-package). In Laravel:
vendor/bin/phpunit --group=wildberries-package # only works if the group lives in your phpunit.xml
More realistically, write your own feature tests against the adapter and use the package tests only as behavioural documentation for what the entities are supposed to do. Add RefreshDatabase + a factory per task model; that's your real safety net.
bin/console is not artisan. Every command in the README is Symfony. Running php artisan baks:assets:install will fail with "command not defined". If there's no Laravel service provider, no Artisan command exists — plan to do each step manually.
Migrations are diff-based, which means they generate your entire schema delta. In a non-empty database that can produce destructive drops. Always run diff against a cloned DB with identical schema, diff the output, and diff the diff before applying. This is the single highest-risk step in the whole integration.
Asset install can overwrite. baks:assets:install copies files into the app. If it can clobber existing config or assets, you lose work silently. Back up, or (better) copy manually once and commit.
PHP 8.4+ is a hard gate. Check CI images, Docker base images, static analysis (PHPStan/Larastan level), and every transitive dependency. This is often more work than the package itself.
Release notes are version stubs (v7.4.37, v7.4.37). There is no meaningful changelog. On every upgrade:
diff -ru vendor/baks-dev/wildberries-package@old vendor/baks-dev/wildberries-package@new
Pin exact versions ("7.4.36", not "^7.4"), commit composer.lock, and treat upgrades as code reviews.
0 stars / 0 dependents = you are the maintainer. Vendor or fork it into app/Wildberries/ or a private VCS repo. Keep a README.internals.md recording: which version you forked, what you changed, and why. If it becomes business-critical, upstream PRs won't be reviewed in time — own the code.
Entity/model ID type mismatch is the classic killer. If package entities use UUIDs and your orders table uses auto-increment BIGINT (or vice versa), you get a painful join layer. Check this in the first schema diff, before writing any code.
Scope ambiguity — verify what actually exists. The README says "Модуль упаковки заказов" (order packaging module). It does not document a Wildberries API client, auth, label generation, inventory sync, or rate limiting. Before promising a feature to stakeholders, grep -r "HttpClient\|Guzzle\|api.wildberries" vendor/baks-dev/wildberries-package/src. If there's no HTTP layer, this is a local task ledger and you're writing the integration yourself.
Dual-ORM transaction hazards. Eloquent and Doctrine hold separate connections/unit-of-work. A DB::transaction() around Eloquent calls does not automatically enlist the EntityManager. Use one ORM per write path, or an explicit shared-connection transaction with both flushed inside it.
Doctrine EntityManager in Octane / long-running workers. $em->clear() after each job batch, and never bind the EntityManager as a singleton without reset semantics. Eloquent devs will not see this coming.
Extension points are thin. With no documented events or interfaces, your extension surface is: the adapter interface you write, config copied into config/wildberries.php, and the queue jobs around it. Don't hunt for hooks that aren't there — put all customization behind your own layer.
Debugging tip: when a packaging task "disappears", check status enum values first. Version-stub releases mean enum cases can shift between minor versions; a varchar status column that silently accepts an unknown value is a common cause of tasks falling out of pending queries.
Exit criteria. Decide before the pilot what "keep it" looks like: e.g. schema review clean, adapter tests green, packaging time down X%, zero status-drift incidents in staging for two weeks. If it fails, deleting a thin adapter layer is cheap — that's exactly why the adapter boundary in Pattern 1 is the one thing you must not skip.
How can I help you explore Laravel packages today?