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

Plug Laravel Package

znck/plug

A collection of pluggable Eloquent traits for Laravel models, adding features like BelongsToThrough, UUID keys, and fixes for belongsTo/morphTo relations. Just use a trait and it boots automatically—no config needed.

View on GitHub
Deep Wiki
Context7

Getting Started

Plug is a grab-bag of Eloquent traits, so onboarding is intentionally small: install, attach a trait to a model, and use whatever behavior it adds. The main risk is that the package predates modern Laravel, so treat the first hour as a compatibility audit rather than a tutorial.

1. Install (and pin)

composer require znck/plug

Because the last tagged release was 2016-09-27, pin an explicit constraint and commit your composer.lock. Do not rely on ^ floating into an incompatible release.

2. Verify the supported versions before writing code

Check composer.json in the vendor directory for the illuminate/* and php constraints. Plug was written for PHP 7.0+ and the Laravel 5.x era. If you are on Laravel 8/9/10+, run a throwaway test model through the trait before adopting it anywhere real — several Eloquent internals it may hook into (bootTraits, model events, $dates, getDateFormat) changed after 5.5.

3. Find out what you actually got

The README is the index, but the source is the truth:

ls vendor/znck/plug/src
# read the trait docblocks — each trait is small and self-describing

Make a list of the traits, the columns/attributes each expects, and whether it registers model events or query scopes. This list is your integration checklist.

4. First use case: one trait on one model

Pick the lowest-risk, highest-value trait — typically a slug/UUID-style attribute generator or a sortable/orderable behavior — and attach it to a single model behind a test.

use Znck\Plug\...; // confirm namespace from src/

class Post extends Model
{
    use HasSlug; // example; verify the actual trait name
}

If the trait needs a column, add it in a migration before saving:

Schema::table('posts', function (Blueprint $table) {
    $table->string('slug')->nullable()->index();
});

5. Sanity check in tinker

php artisan tinker
>>> $p = Post::create(['title' => 'Hello World']);
>>> $p->fresh()->slug;

If that works, you have proven the boot path, the attribute assignment, and the persistence path. Only then roll it out to other models.

Implementation Patterns

Compose traits on a shared base model

If several models need the same behaviors, a project-level BaseModel is cleaner than repeating use blocks and keeps the Plug dependency in one place:

abstract class BaseModel extends Model
{
    use HasUuid;      // example
    use Sortable;     // example
}

This also gives you one file to change if you later replace Plug with an in-house trait.

Let trait boot methods do their work

Eloquent traits can define boot{TraitName}() methods that register events and global scopes automatically. Do not duplicate that logic in your model's boot() — you will get double registration (double slug generation, duplicate observers). Instead, read what the trait's boot method does and build around it.

Wrap trait behavior in your own scopes for query readability

Traits that expose scopes are best used through your own domain vocabulary so call sites stay readable and refactorable:

public function scopePublished(Builder $q)
{
    return $q->where('published_at', '<=', now());
}

// usage
Post::published()->latest()->paginate();

Use observers/factories alongside traits, not inside them

Traits handle per-model attribute concerns; cross-cutting concerns (notifications, indexing, audit logs) belong in observers or events. This keeps the trait surface small and makes it easy to drop Plug later:

Post::observe(PostObserver::class);

Control serialization deliberately

Traits that add computed attributes often need to be surfaced in API responses. Declare that explicitly rather than relying on the trait's defaults:

protected $appends = ['slug'];
protected $hidden  = ['internal_key'];

Seed and test through the model, not raw inserts

If a trait generates attributes on creating/saving, raw DB::table()->insert() will bypass it and leave inconsistent rows. Use factories and Model::create() so trait hooks run:

$post = Post::factory()->create(['title' => 'Seeded']);

Wrap third-party traits in your own

For anything you plan to keep long-term, define an application trait that uses the Plug trait. That single indirection point means replacing an abandoned dependency becomes a one-file change:

trait AppHasSlug
{
    use \Znck\Plug\...\HasSlug; // example
}

Gotchas and Tips

Maturity is the headline risk. Last release 2016, 13 stars, zero dependents. Assume no upstream fixes. Budget for a fork: vendor the handful of traits you actually use into app/Support/Eloquent/ and drop the Composer requirement. Most of these traits are 20–80 lines of code.

Laravel version drift is the likeliest breakage. Test on your exact framework version before adopting. Watch for:

  • Boot method signatures and bootTraits() behavior
  • $dates / $casts handling changes
  • Event registration and global scope APIs
  • Return types added in newer Eloquent (Model::newQuery(): Builder, etc.)

Trait conflicts are silent until they explode. Two traits (yours or Plug's) may declare the same method or property. PHP fatal-errors at class declaration, not at call time, so run your test suite after each new use statement. Alias when needed:

use HasSlug { generateSlug as generateBasicSlug; }

Mass assignment bites generators. If a trait sets an attribute in creating, that attribute does not need to be in $fillable — but if you also allow it to be set from request input, you must guard it. Decide per trait whether the value is user-controlled or generated.

Column requirements are not enforced. Missing columns fail at save time with a database error, not a helpful exception. Keep a short docblock on each model noting which trait expects which column, and add those columns in the same migration that introduces the trait.

Debugging tip: enumerate what is actually attached.

dump(class_uses_recursive(Post::class));
dump(get_class_methods(Post::class));

If a scope or accessor is missing, the trait probably failed to attach or its boot method never ran. Compare class_uses() against the trait's own boot method name — a typo there means the hook is silently never registered.

Watch for N+1s from trait accessors. Traits that derive attributes from relationships or queries can turn a 20-row index into 40 queries. Eager-load the underlying relation in the controller and confirm with DB::listen() or Laravel Telescope before shipping.

Check for a config/publishable surface. If the package ships a config file or service provider, publish and review it early (php artisan vendor:publish). Defaults from 2016 may not match your conventions, and leaving them unpublished makes behavior invisible.

Extension points are limited — use yours instead. Do not subclass the traits or monkey-patch vendor files. Extend via:

  • Your own trait wrapping the Plug trait
  • Model observers for event-based behavior
  • Local scopes for query behavior

Pin and document the exit path. Add a line to your README or architecture notes: "Depends on znck/plug for X, Y, Z; replacement plan: local traits in app/Support/Eloquent." When a Laravel upgrade eventually breaks it, you will know exactly what to port instead of grepping for the namespace under pressure.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route