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

Base Models Laravel Package

brokeyourbike/base-models

brokeyourbike/base-models provides reusable base Eloquent model classes for Laravel, giving your models sensible defaults for casting, timestamps, and common query behavior. Extend these foundations to keep model code consistent and cut boilerplate across your app.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and inspect before you wire it in.

composer require brokeyourbike/base-models
composer show -a brokeyourbike/base-models   # confirms version + PSR-4 autoload mapping

With zero stars, zero dependents, and a single release from May 2023, treat this as read-the-source-first code. The entire package is a base class — it should be a few hundred lines at most. Open vendor/brokeyourbike/base-models/src/ and read it end to end before adopting. You are looking for:

  • the abstract class name and namespace (confirm the PSR-4 root from composer.json),
  • what it sets that Illuminate\Database\Eloquent\Model does not — typically $guarded = [] vs $fillable, $hidden, $casts, $dateFormat, $keyType/$incrementing, connection defaults,
  • whether it adds traits (HasFactory, SoftDeletes), global scopes, or booted() hooks that fire silently.

2. First use case: a single new model.

namespace App\Models;

use Brokeyourbike\BaseModels\Model as BaseModel; // verify exact FQCN

class Post extends BaseModel
{
    protected $fillable = ['title', 'body'];
}

Verify nothing surprising is inherited:

php artisan tinker
>>> (new App\Models\Post)->getTable();
>>> (new App\Models\Post)->getGuarded();
>>> (new App\Models\Post)->getDates();
>>> (new App\Models\Post)->getConnectionName();

3. Decide the adoption shape early. Two options: extend the package class directly in every model (tight coupling to an unmaintained dependency), or extend it once in App\Models\BaseModel and have all your models extend that (a one-line seam you can sever later). For a 0-star package, the second option is the only defensible one — see the Gotchas section.

Implementation Patterns

Wrap it in your own base class. This is the pattern that makes the package swappable:

namespace App\Models;

abstract class BaseModel extends \Brokeyourbike\BaseModels\Model
{
    // Pin down anything the package leaves implicit
    protected $guarded = [];
}

Every app model extends App\Models\BaseModel. If the package is abandoned (likely, given the 2023 release and no activity), you swap the parent to Illuminate\Database\Eloquent\Model and inline whatever you actually relied on. Nothing else in the codebase changes.

Migrate existing models incrementally. Do not bulk-replace extends Model across the codebase. Pick one model, switch it, run the full test suite, and inspect the diff in behaviour. A base class that changes $guarded, $casts, or $dates will alter mass-assignment and serialization silently — tests catch this only if you assert on toArray() and on MassAssignmentException.

Audit for defaults that leak into JSON. If the base model sets $hidden or $visible, every API response shape changes. Add a response assertion test per resource before migrating.

Use it as the anchor for shared behaviour in a multi-model app. The genuine value of a project base model is the seam where you add: a HasFactory resolution override, a booted() hook for common observers, a scopeActive(), UUID/ULID key generation, or a toArray() that normalises dates. Layer those on your App\Models\BaseModel, not by forking the vendor package.

Factories. If the package includes HasFactory, Laravel resolves Database\Factories\{Model}Factory by class name. Extending a base class doesn't change that resolution, but a base class that overrides newFactory() does — check src/ for newFactory before assuming default factory discovery works.

Testing. In tests/, assert the contract you depend on rather than the package's behaviour generally:

public function test_base_model_contract(): void
{
    $model = new \App\Models\Post;
    $this->assertSame([], $model->getGuarded());
    $this->assertSame('posts', $model->getTable());
}

This test is your tripwire if you later swap the parent class — it documents exactly what you needed from the package.

Gotchas and Tips

Abandonment is the primary risk, not bugs. One release in 2023, no dependents, no stars. Budget for the day it stops receiving Laravel-version-compatible updates. The wrapper pattern above converts that event from a refactor into a one-line change. Check compatibility with your Laravel version explicitly — a base model touching Eloquent internals (getDateFormat(), asDateTime(), newEloquentBuilder()) can break across major versions.

MPL-2.0 is file-level copyleft. You can use and distribute it inside a proprietary app freely, and extending the class is ordinary use. But if you modify the package's own source files, those modified files must be made available under MPL-2.0. Practical consequence: never edit vendor/ — publish/override in your own App\Models\BaseModel instead. This keeps your obligations at zero.

$guarded = [] is the classic surprise. Many base models ship with it for convenience. That means every column is mass-assignable, including is_admin, role, balance. If the package sets it, override per-model with explicit $fillable on anything user-facing, and never expose create($request->all()).

Global scopes in booted() are invisible and sticky. If the base class registers a global scope (soft-delete-adjacent filtering, tenancy, ordering), it applies to every query including exists(), update(), and relationship queries. Look for static::addGlobalScope in src/ and in any traits it pulls in. Debug with Model::withoutGlobalScopes()->toSql().

$casts merge semantics. protected $casts on a child class replaces the parent array in older Laravel and merges in newer ones depending on how it's declared ($casts property vs casts() method). If the base model casts id to int or dates to immutable_datetime, verify your child models keep those casts after adding their own. When in doubt, override the casts() method and call parent::casts().

Debugging inherited config. When a model behaves unexpectedly, dump the resolved values rather than reading source:

$m = new App\Models\Post;
dump($m->getGuarded(), $m->getCasts(), $m->getDates(), $m->getHidden());

Or php artisan model:show App\\Models\\Post, which surfaces table, attributes, and relations but not global scopes — use Post::getGlobalScopes() separately.

Connection and table defaults. If the base model pins $connection or derives $table from a custom convention (e.g. snake-case plural of a namespaced class), models moved between namespaces will resolve to the wrong table. Always set $table explicitly on models whose namespace isn't App\Models.

Extension points to prefer over forking. Traits on your own BaseModel, per-model property overrides, booted() in the child, and model events — all of these survive a package swap. Subclassing an abstract method from the vendor class, or overriding a method the vendor class calls internally, does not.

Version pin it. In composer.json, constrain to ^1.0 (or whatever the released line is) rather than *, and commit composer.lock. With no maintainer activity, an unexpected tag is more likely to be a mistake than an improvement.

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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core