PHPackages                             whilesmart/eloquent-products - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. whilesmart/eloquent-products

ActiveLibrary[Database &amp; ORM](/categories/database)

whilesmart/eloquent-products
============================

Polymorphic product and service catalog for Laravel applications.

04PHP

Since Apr 25Pushed 1mo agoCompare

[ Source](https://github.com/whilesmartphp/eloquent-products)[ Packagist](https://packagist.org/packages/whilesmart/eloquent-products)[ RSS](/packages/whilesmart-eloquent-products/feed)WikiDiscussions dev Synced 1w ago

READMEChangelogDependenciesVersions (3)Used By (0)

whilesmart/eloquent-products
============================

[](#whilesmarteloquent-products)

Polymorphic product / service catalog for Laravel applications. Implements `Whilesmart\Invoices\Contracts\Invoiceable` so every product can be referenced as a line item by `whilesmart/eloquent-invoices`.

Install
-------

[](#install)

```
composer require whilesmart/eloquent-products
php artisan migrate
```

`whilesmart/eloquent-invoices` is a hard dependency — composer pulls it in automatically because every Product implements its `Invoiceable` contract.

Use
---

[](#use)

Add `HasProducts` to any model that should own a catalog (Workspace, Organization, User, …):

```
use Whilesmart\Products\Traits\HasProducts;

class Workspace extends Model
{
    use HasProducts;
}
```

Create products and services:

```
$workspace->products()->create([
    'type'                => 'product',
    'sku'                 => 'SHN-30YR',
    'name'                => '30-year asphalt shingles',
    'default_unit'        => 'bundle',
    'default_price_cents' => 4200,
    'currency'            => 'USD',
]);

$workspace->products()->create([
    'type'                => 'service',
    'sku'                 => 'LBR-ROOF',
    'name'                => 'Roofing labour',
    'default_unit'        => 'hour',
    'default_price_cents' => 7500,
]);
```

Then drop them onto an invoice without retyping anything:

```
$invoice->lineItems()->create([
    'invoiceable_type' => Product::class,
    'invoiceable_id'   => $shingles->id,
    'quantity'         => 12,
]);
```

The line item gets `description`, `default_unit`, and `default_price_cents` snapshotted from the product at create time.

Endpoints
---------

[](#endpoints)

VerbPathNotes`GET``/api/products`List, filter by `owner_type`+`owner_id`, `type`, `category`, `is_active`, search via `?q=``POST``/api/products`Create`GET``/api/products/{id}`Show`PUT``/api/products/{id}`Update`DELETE``/api/products/{id}`Soft deleteType enum
---------

[](#type-enum)

`Whilesmart\Products\Enums\ProductType`: `product` (physical / unit-priced) or `service` (time / rate-priced). Same model, single table.

Schema
------

[](#schema)

`products` table:

columntypeidbigintowner\_type / owner\_idmorphstypestring (enum)skunullable string, unique per ownernamestringdescriptiontextdefault\_unitnullable stringdefault\_price\_cents / default\_cost\_centsbigintdefault\_tax\_ratedecimal(6,4) nullablecurrencychar(3)categorynullable stringis\_activebooleanmetadatajsontimestamps + soft deletesScope
-----

[](#scope)

This package does **one thing**: store the reusable definition of a product or service. Adjacent concerns live in their own packages:

- Inventory levels / stock counts → `whilesmart/eloquent-inventory` (later)
- Multi-tier / multi-currency price lists → `whilesmart/eloquent-pricing` (later)
- Bundles / kits → on top of the same products table, later

Config
------

[](#config)

Publish with `php artisan vendor:publish --tag=products-config`. Override `register_routes`, `route_prefix`, `route_middleware`, and `table` via env or the published config file.

###  Health Score

21

—

LowBetter than 18% of packages

Maintenance60

Regular maintenance activity

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity15

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/a1ca6f6e01ecbfe6640ff410c4f0321054fb48d05a5f843c2b89887b90369bcd?d=identicon)[whilesmart](/maintainers/whilesmart)

---

Top Contributors

[![nfebe](https://avatars.githubusercontent.com/u/14317775?v=4)](https://github.com/nfebe "nfebe (5 commits)")

### Embed Badge

![Health badge](/badges/whilesmart-eloquent-products/health.svg)

```
[![Health](https://phpackages.com/badges/whilesmart-eloquent-products/health.svg)](https://phpackages.com/packages/whilesmart-eloquent-products)
```

###  Alternatives

[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k116.5M113](/packages/jdorn-sql-formatter)[propel/propel1

Propel is an open-source Object-Relational Mapping (ORM) for PHP5.

8361.6M87](/packages/propel-propel1)[mpociot/laravel-composite-key

Support composite keys in your laravel app.

3544.8k1](/packages/mpociot-laravel-composite-key)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
