amarenkov/laravel-mutable-content-shop
A practical Laravel package for mutable-content shops that provides building blocks to manage and dynamically update storefront content. It helps Laravel developers keep product listings, pages, and other shop content editable, organized, and easy to maintain within their applications.
Install the package and publish its assets:
composer require mutable-content/shop
php artisan vendor:publish --tag=mutable-content-shop-config
php artisan vendor:publish --tag=mutable-content-shop-migrations
php artisan migrate
Set invoices_disk in config/mutable-content-shop.php to a valid filesystem disk (e.g. local or s3). If you need custom models or states, review models.invoice, lovs.order_state, and lovs.order_item_state in the same config file. For a first use case, create an order and attach an invoice:
$order = Order::create([...]);
$invoice = $order->invoices()->create([
'number' => 'INV-001',
'date' => now(),
'money' => 10000, // amount in minor units, depending on money package
'paid_amount' => 2500,
'comment' => 'First invoice',
]);
$invoice->due(); // remaining amount
$order->invoicedTotal(); // sum of invoice amounts
$order->paidTotal(); // sum of paid amounts
Look first at the Invoice model (fields, due(), hasFile(), Invoice::disk()) and the Order model (invoices(), invoicedTotal(), paidTotal()).
Invoice creation and payment state – Set money and paid_amount; the invoice_payment_state LOV (unpaid, partially_paid, paid) is recalculated automatically on save. Avoid setting the state manually unless you have a custom requirement. Use the state for filtering and reporting.
File attachments – Store documents on the disk returned by Invoice::disk() (driven by invoices_disk). Check existence with $invoice->hasFile(). Upload via Storage::disk(Invoice::disk())->putFile('invoices', $file) and save the path on the invoice.
Totals for dashboards – Order::invoicedTotal() and paidTotal() are convenient for order summaries. Eager load invoices when iterating orders to avoid N+1 queries.
Extending state LOVs – Create a subclass of the relevant LOV class (e.g. OrderState), add your own constants, and point lovs.order_state or lovs.order_item_state to your class. This keeps package behaviour intact while allowing domain‑specific states.
Custom models – Swap models.invoice in config to your own class extending the base Invoice. Ensure it preserves the package’s table name and the static disk() method. Publish only the invoice migration with the mutable-content-shop-migrations tag when you already have other shop tables.
DomainException – paid_amount must use the same currency as money. Validate or convert before saving to avoid runtime exceptions.invoices_disk, models.invoice, or LOV classes, run php artisan config:clear. Cached config can cause confusing behaviour in production.invoices_disk is not a valid disk, file operations fail. Test Storage::disk(Invoice::disk())->exists(...) early. Do not assume local storage.mutable-content-shop-migrations may attempt to recreate existing tables. Use the tag carefully and review the generated migration before running migrate.due() return type – It likely returns a money object, not a scalar. Use its API (e.g. ->getAmount()) for comparisons or formatting. Do not cast directly to float.invoicedTotal() and paidTotal() aggregate across invoices. Cache results or use eager‑loaded collections for large order lists.How can I help you explore Laravel packages today?