Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Suitable Laravel Package

laravolt/suitable

Laravolt Suitable is a Laravel package for adding approval workflows to Eloquent models. It provides configurable statuses, reviewer actions, and history tracking so records can be submitted, approved, or rejected with a clear audit trail.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, additive patch (3.6.12) on the 3.6 line. There are no breaking changes, no deprecations, and no config migrations — upgrading is a composer update away. The only behavioural change is that search definitions can now target JSON columns using Laravel's -> path syntax.

Start by reading the package's search/trait entry point and its config file (usually published via php artisan vendor:publish). The first thing to confirm is how searchable columns are declared — most packages of this shape expose either a $searchable array on the model or a searchable() method returning column names. The new release simply means any entry in that list can now be a JSON path such as meta->title rather than only a flat column.

A minimal first use case:

use Illuminate\Database\Eloquent\Model;
use Vendor\Package\Concerns\Searchable;

class Product extends Model
{
    use Searchable;

    // Flat columns continue to work exactly as before.
    protected array $searchable = [
        'name',
        'sku',
        'meta->title',      // new in 3.6.12
        'meta->tags',       // new in 3.6.12
    ];
}

Then:

Product::search('widget')->paginate(25);

Verify it on a scratch route or tinker session before wiring it into a controller. If you are upgrading an existing app, the fastest sanity check is to run your existing search test suite unchanged — it should be green — and then add one new test that searches a JSON path.

Implementation Patterns

Progressive adoption. Keep flat columns in the searchable list and add JSON paths incrementally. Because the syntax is identical to Laravel's own where('meta->title', ...), you can prototype a query with the plain query builder first, confirm the generated SQL, then move the column into the searchable definition. This avoids guessing at how the package composes its orWhere group.

Search endpoint pattern. Wrap the call in a form request and a thin controller action so the search term is validated and trimmed before it reaches the package:

public function index(SearchProductsRequest $request)
{
    return Product::query()
        ->search($request->validated('q'))
        ->with('category')
        ->paginate(25)
        ->withQueryString();
}

withQueryString() matters — search UIs almost always need the term preserved across pages.

Combining with existing scopes. The search constraint is just another query constraint, so chain it after your tenancy/visibility scopes rather than before:

Product::query()
    ->where('tenant_id', tenant()->id)
    ->where('is_active', true)
    ->search($term)
    ->get();

Ordering the search last keeps the intent readable and makes it obvious which constraints are security-relevant.

Typed search objects. If several endpoints search the same model with different column sets, extract named methods or small query objects (ProductSearch::active($term)) instead of duplicating column arrays. The JSON path syntax being a string makes it easy to drift; centralising it keeps your meta->title and meta->tags definitions in one place.

Testing. Use SQLite in-memory for feature tests, but be aware JSON path behaviour differs between drivers (see below). For anything that depends on JSON search semantics, add at least one test against the same engine you run in production — MySQL or Postgres — via a CI matrix or a dedicated test connection.

Migration note. Nothing to change in existing code. The 3.6.12 change is purely "you can now write -> in the searchable list", so treat it as a new capability to adopt, not a migration task.

Gotchas and Tips

Driver differences are the big one. -> behaves differently across engines. MySQL and SQLite implement it with json_extract, PostgreSQL uses #> / ->> and is case- and type-sensitive. A search that returns results locally on SQLite may return nothing on Postgres because the extracted value is json rather than text. If your searches silently stop matching on JSON paths in production, this is almost always the cause — check the generated SQL with ->toSql() and ->getBindings().

Quoting and ->>. Laravel distinguishes -> (returns JSON) from ->> (returns unquoted text). The package supports ->; if you find that LIKE comparisons against a JSON path behave unexpectedly, test whether you need the unquoted variant. Do not assume the package rewrites -> into ->> for you.

Do not interpolate user input into the path. The column/path portion must come from your own code, never from the request. Only the search term should be user-controlled. A path built from $request->input('column') is an injection and error surface.

Wildcards and empty terms. Most implementations wrap the term in %...%. A term that is only % or _ will match everything, and an empty string may either match all rows or produce LIKE '%%'. Guard at the request layer: reject blank terms with a validation rule and escape % / _ if your package does not do it for you.

JSON paths are not indexed by default. A LIKE '%term%' against meta->title is a full scan on MySQL unless you add a generated column and index it, or use a functional index on Postgres. For large tables, plan for a generated column plus index rather than relying on the package to make it fast. This release adds correctness for JSON search, not performance.

Arrays and nested paths. meta->tags where the value is a JSON array will not behave like a text column. Decide early whether array membership is in scope; if it is not, keep array-valued keys out of the searchable list to avoid confusing partial matches.

Debugging checklist. When a JSON search returns nothing: (1) confirm the row exists and the path is correct with a raw where('meta->title', 'like', ...); (2) dump toSql() and run it manually; (3) confirm the DB driver; (4) confirm the term is non-empty and trimmed. Working through these four in order resolves nearly every report.

Extension points. If the package exposes a per-column callback or a custom search-strategy hook, that is the right place to add driver-specific handling (e.g. casting to text on Postgres) rather than subclassing the model or overriding the trait method — the latter is fragile across patch releases like this one.

Version pinning. 3.6.12 is a patch release; pin to ^3.6 and let patch upgrades through, since this line is additive. Re-read the release notes on any 3.7 minor for changes to how paths are parsed.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums