4.6 KiB
Contributing to boboko-core
This is a Composer library, not a runnable app — you can't php artisan serve it directly. To develop and verify changes, you need a consumer app wired to a local checkout via a Composer path repository, plus a real database, since a large part of this package (Lunar models, migrations, Filament panel resources) can only be meaningfully verified against a live Lunar install.
Local dev setup
This works against any consumer app that follows the same convention — boboko-test, boboko-starter, boboko-3dealer, etc. — checked out next to this repo:
RadicalElements/
├── boboko-core/ (this repo)
└── boboko-test/ (or boboko-starter, boboko-3dealer, ... — consumer app, Docker-based)
Each of these consumer apps ships a bin/dc-core.sh helper that wraps the Docker Compose overlay needed to bind-mount a local boboko-core checkout into the app container:
./bin/dc-core.sh exec app <command>
This is shorthand for docker compose -f docker-compose.dev.yml -f docker-compose.core-dev.yml exec app <command>. Use ./bin/dc-core.sh for everything below instead of typing the full compose invocation.
-
Path repository. In the consumer app's
composer.json, therepositoriesarray needs a path entry pointing at../boboko-core. If it only exists in a disabled block (e.g._repositories), move it into the live array. -
Relaxed version constraint. The consumer app's
composer.jsonshould require"boboko/core": "0.*"(not a tight^0.0.1caret) — otherwise Composer rejects newer0.0.xversions resolved from the path repo. -
Bind mount. The consumer app's
docker-compose.core-dev.ymloverlays../boboko-coreinto the container at/var/www/boboko-core, matching where the path repo resolves it relative to/var/www/html. -
Re-resolve after every change. Composer's path repo does not hot-reload — after editing anything in
boboko-core(including adding new files, which need autoload discovery), the container needs to re-runcomposer update boboko/core. Inboboko-test, the entrypoint does this automatically on every dev boot (seedocker/entrypoint.sh), so./bin/dc-core.sh upalone picks up local core changes. If a consumer app's entrypoint doesn't do this yet, run it manually:./bin/dc-core.sh exec app composer update boboko/core --with-all-dependenciesSkipping this step is the most common cause of "my change isn't showing up."
Verifying changes against a real database
There is no automated test suite for this package — too much of Lunar's behavior (table prefixing, nested sets, translatable attributes, Filament panel filters) only breaks in combination, against real Postgres, in a way that's impractical to fake in isolation. Instead, verify changes directly against a consumer app's live database. The practical workflow used throughout this package's MigrateImport feature:
One-off checks, via php artisan tinker --execute="..." in the consumer app's container:
./bin/dc-core.sh exec app php artisan tinker --execute="
use Modules\Core\MigrateImport\Shopify\Resolvers\ProductTypeResolver;
\$type = (new ProductTypeResolver())->resolve('Test Type');
echo \$type->name . PHP_EOL;
"
Multi-step scripts (creating related records, checking round-trips), via a raw PHP script bootstrapped like an Artisan command — this avoids tinker's persistent-session quirks and more closely matches how code actually runs in a queued job:
./bin/dc-core.sh exec app php -r "
require 'vendor/autoload.php';
\$app = require 'bootstrap/app.php';
\$kernel = \$app->make(Illuminate\Contracts\Console\Kernel::class);
\$kernel->bootstrap();
// ... your verification code ...
"
Always clean up fixtures created this way — either via DB::statement('DELETE FROM ...') in the same script (respecting foreign key order — Lunar has cascading relations like lunar_customer_group_product that block naive deletes), or leave them if they're harmless and the DB is a disposable dev/test instance.
Non-obvious Lunar bugs/traps hit while building against it are documented in docs/lunar.md, not here — check there before debugging something that looks like a Lunar quirk.
Code organization
Feature work lives under src/<Feature>/, with models in a Models/ subdirectory (see src/Auth/Models, src/Customer/Models, src/MigrateImport/Models). Source-specific importer logic is grouped by source name (e.g. src/MigrateImport/Shopify/), with resolver classes (one responsibility each — resolve-or-create a single Lunar entity) grouped further under Resolvers/.