PHPackages                             baconfy/variants - 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. [API Development](/categories/api)
4. /
5. baconfy/variants

ActiveLibrary[API Development](/categories/api)

baconfy/variants
================

Composable API resources for Laravel via server-side variants

v1.0.0(2w ago)00AGPL-3.0-onlyPHPPHP ^8.2CI passing

Since May 19Pushed 6d agoCompare

[ Source](https://github.com/baconfy/variants)[ Packagist](https://packagist.org/packages/baconfy/variants)[ RSS](/packages/baconfy-variants/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (7)Versions (3)Used By (0)

 [![Prompt](https://raw.githubusercontent.com/baconfy/variants/main/docs/presentation.jpg)](https://raw.githubusercontent.com/baconfy/variants/main/docs/presentation.jpg)

[![Tests](https://github.com/baconfy/variants/actions/workflows/tests.yml/badge.svg)](https://github.com/baconfy/variants/actions/workflows/tests.yml)[![Latest Version](https://camo.githubusercontent.com/e1214a81dce69a0788d920c5bd091ab3a390ec0218e9b720fc55b3f16999e54e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6261636f6e66792f76617269616e74732e737667)](https://packagist.org/packages/baconfy/variants)[![License](https://camo.githubusercontent.com/988da18918989b52632050deb6e57513ab19f11897dcebe8133b79b37c41e005/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6261636f6e66792f76617269616e74732e737667)](https://packagist.org/packages/baconfy/variants)[![Total Downloads](https://camo.githubusercontent.com/5e0eb7ba1ee00a500cde1cc615b1511ca0b176a17bf02bfdab4f3440fd99fdf1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6261636f6e66792f76617269616e74732e737667)](https://packagist.org/packages/baconfy/variants)[![PHP Version](https://camo.githubusercontent.com/1772bee975e6bbe055113ccccaf2d7e1ed9d29247b6fba82b73d6a9922dcbaaa/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f6261636f6e66792f76617269616e74732e737667)](https://packagist.org/packages/baconfy/variants)

baconfy/variants
================

[](#baconfyvariants)

Composable API resources for Laravel. Define named blocks, group them into variants, and select the right shape per endpoint — all in one class, no controllers bloated with conditional fields.

Installation
------------

[](#installation)

```
composer require baconfy/variants
```

Requires PHP 8.2+ and Laravel 12+.

Minimal example
---------------

[](#minimal-example)

### 1. Define a resource

[](#1-define-a-resource)

```
use Baconfy\Variants\ComposableResource;
use Illuminate\Http\Request;

final class ProductResource extends ComposableResource
{
    protected function core(): array
    {
        return [
            'id'   => $this->resource->id,
            'name' => $this->resource->name,
        ];
    }

    protected function pricing(): array
    {
        return ['price' => $this->resource->price];
    }

    protected function full(): array
    {
        return ['description' => $this->resource->description];
    }

    protected function locale(Request $request): array
    {
        return ['locale' => $request->header('Accept-Language', 'en')];
    }

    protected function variants(): array
    {
        return [
            'list' => ['core', 'pricing'],
            'show' => ['core', 'pricing', 'full'],
            'i18n' => ['core', 'locale'],
        ];
    }

    protected function default(): string
    {
        return 'list';
    }
}
```

### 2. Use it

[](#2-use-it)

```
// Default variant (list → core + pricing)
ProductResource::make($product);

// Named variant
ProductResource::make($product)->as('show');

// Variant + extra block
ProductResource::make($product)->as('list')->with('full');

// Ad-hoc selection — no variant, just the blocks you name
ProductResource::make($product)->only('core', 'full');

// Collection — variant propagates to every item
ProductResource::collection($products)->as('list');

// Collection — variant + extra blocks
ProductResource::collection($products)->as('list')->with('full');
```

### 3. Resolve in a controller

[](#3-resolve-in-a-controller)

```
public function index(): JsonResponse
{
    return ProductResource::collection(Product::paginate())
        ->as('list')
        ->response();
}

public function show(Product $product): JsonResponse
{
    return ProductResource::make($product)
        ->as('show')
        ->response();
}
```

API reference
-------------

[](#api-reference)

MethodDescription`::make($model)`Single resource, default variant`::collection($items)`Collection, default variant`->as(string $variant)`Switch to a named variant`->with(string ...$blocks)`Append extra blocks (additive, chainable)`->only(string ...$blocks)`Replace selection with exactly these blocks, no variant`->resolve($request?)`Resolve to plain array`->response($request?)`Return `JsonResponse`How blocks work
---------------

[](#how-blocks-work)

A block is any `protected` method on your resource class that:

- returns `array`
- is listed in at least one variant inside `variants()`
- optionally accepts `Illuminate\Http\Request` as its first (and only) parameter

Helper methods on the resource class that are **not** listed in `variants()` cannot be called via `with()` or `only()` — this is intentional. The `variants()` array is the single source of truth for what is a block.

Exceptions
----------

[](#exceptions)

All exceptions extend `\RuntimeException`.

### `UnknownVariantException`

[](#unknownvariantexception)

Thrown by `->as()` when the variant name is not a key in `variants()`. Also thrown at first instantiation if `default()` returns a name not in `variants()`.

```
Unknown variant [xyz] on [App\Http\Resources\ProductResource]. Available: [list, show, i18n].

```

### `UnknownBlockException`

[](#unknownblockexception)

Thrown by `->with()` and `->only()` immediately (not at resolve time) when a block name is not referenced in any variant. Also thrown at first instantiation if a variant references a method that does not exist on the class.

```
Unknown block [xyz] on [App\Http\Resources\ProductResource]. Available: [core, pricing, full, locale].

```

### `DuplicateBlockKeyException`

[](#duplicateblockkeyexception)

Thrown at resolve time when two blocks in the active selection return the same top-level key.

```
Duplicate key [name] in [App\Http\Resources\ProductResource]: produced by both [core] and [alias].

```

Notes on `with()` and PHP compatibility
---------------------------------------

[](#notes-on-with-and-php-compatibility)

`JsonResource::with($request)` is an existing method used internally by Laravel's resource response layer. PHP's method compatibility rules prevent overriding it with `with(string ...$blocks): static`, so the parameter type is declared `mixed`. The method body validates string types and guards against the internal `Request` call. Runtime behaviour is identical to what the spec describes.

License
-------

[](#license)

AGPL-3.0-only — see [LICENSE](LICENSE).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance98

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 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.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

20d ago

Major Versions

v0.1.0 → v1.0.02026-05-20

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7077461?v=4)[Renato Dehnhardt](/maintainers/rdehnhardt)[@rdehnhardt](https://github.com/rdehnhardt)

---

Top Contributors

[![rdehnhardt](https://avatars.githubusercontent.com/u/7077461?v=4)](https://github.com/rdehnhardt "rdehnhardt (7 commits)")

---

Tags

laravelvariantsapi resourcecomposablejson-resource

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/baconfy-variants/health.svg)

```
[![Health](https://phpackages.com/badges/baconfy-variants/health.svg)](https://phpackages.com/packages/baconfy-variants)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

815320.5k3](/packages/defstudio-telegraph)[resend/resend-laravel

Resend for Laravel

1212.2M8](/packages/resend-resend-laravel)[essa/api-tool-kit

set of tools to build an api with laravel

53286.5k](/packages/essa-api-tool-kit)[simplestats-io/laravel-client

Analytics for Laravel. Track visitors, registrations, and payments. Discover which channels actually drive revenue, not just traffic. Server-side, GDPR compliant, ad-blocker proof.

5019.3k](/packages/simplestats-io-laravel-client)[joggapp/laravel-aws-sns

Laravel package for the SNS events by AWS

3175.9k](/packages/joggapp-laravel-aws-sns)

PHPackages © 2026

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