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

Database Laravel Package

graham-campbell/database

A Laravel database package from Graham Campbell that provides a streamlined, configurable database layer with multiple connections and seamless integration with Laravel's query builder and Eloquent for simple, consistent data access.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: graham-campbell/database is an archival Laravel 4.2 package. The repo lives under GrahamDeprecated, the only release is v0.1.4-alpha, and it has zero dependents. There is no forward path to Laravel 5+. The only two legitimate reasons to touch it are (a) you are already maintaining a frozen L4.2 app that depends on it, or (b) you want a small, readable reference for a repository layer you intend to write yourself. Everything below assumes one of those.

Minimal install (legacy L4.2 app only):

  1. Require it with the alpha flag — the tag is not stable, so Composer will refuse to resolve it otherwise:

    composer require graham-campbell/database:~0.1@alpha
    

    If your root composer.json still has "minimum-stability": "stable", either raise it to dev (and pin everything else) or rely on the @alpha inline flag. Expect PHP 5.4–5.6 constraints from the transitive illuminate/* pins.

  2. Register the provider in app/config/app.php under providers:

    'GrahamCampbell\Database\DatabaseServiceProvider',
    

    Confirm the exact FQCN against src/ in the checkout — the README is thin, and the provider name is the very first thing to verify. Register it after any provider you depend on.

  3. Publish config only if the package actually ships one:

    php artisan config:publish graham-campbell/database
    

    If src/config/ doesn't exist, skip this — don't invent a config file.

  4. Where to look first: open the base repository class in src/ (typically something like GrahamCampbell\Database\Repository). Its method signatures — find, findOrFail, create, update, delete, paginate — are the real documentation. Read the constructor too; that's where the model/connection resolution contract lives, and it's the part that determines how you wire subclasses.

  5. First use case — thin out one fat controller. Pick a simple model and make a repository:

    use GrahamCampbell\Database\Repository;
    
    class PostRepository extends Repository
    {
        protected $model = 'Post';
    }
    

    Then resolve and use it:

    $post = App::make('PostRepository')->find($id);
    

    Verify a full round-trip (create → find → update → delete) on a throwaway record before widening adoption to other controllers.

Implementation Patterns

One repository per aggregate root. PostRepository, UserRepository, OrderRepository — each extending the base and declaring its model. Resist a god-repository; the package gives you composition for free and the L4.2 app/repositories/ convention maps onto it cleanly.

Bind interfaces, inject repositories. Don't call App::make() in controllers. In a RepositoryServiceProvider registered after the package provider:

App::bind('PostRepositoryInterface', 'PostRepository');

Controllers then type-hint the interface:

public function __construct(PostRepositoryInterface $posts)
{
    $this->posts = $posts;
}

This is the entire payoff of the package — a single seam you can swap, mock, or decorate later.

Route all reads/writes through the base helpers. The daily flow should never reach for Post::find() directly:

$post   = $this->posts->find($id);
$post   = $this->posts->findOrFail($id);
$new    = $this->posts->create(Input::all());
$updated = $this->posts->update($id, Input::all());
$this->posts->delete($id);

If a helper you expect isn't in the base class, add it on your subclass rather than leaking Eloquent into the controller.

Keep pagination and limit policy in the repository. Wrap paginate($perPage) and limit($n) so page-size lives in one place. Controllers should ask for "a page" without knowing the number:

public function index()
{
    return View::make('posts.index', ['posts' => $this->posts->paginate(20)]);
}

Changing the default page size then becomes a one-line edit, not a grep.

Use the cache-aware read paths deliberately. If the base repository exposes cached reads, treat that as an opt-in per method rather than a global default — wrap it in a named method on your subclass (findCached($id)) so the call site documents the staleness contract. Don't let caching appear implicitly on find().

Testing seam. Because everything resolves through the container, tests can App::instance('PostRepositoryInterface', $mock) and assert controller behaviour without a database. This is the strongest argument for the pattern — and the one worth copying even if you drop the package. For the persistence layer itself, integration-test the repository against a real (SQLite) database; unit-test controllers against a mock.

Porting the idea to modern Laravel (the recommended path). The abstraction is ~150–250 lines. In a Laravel 10/11 app, write it in-house:

abstract class BaseRepository
{
    public function __construct(protected Model $model) {}

    public function find(int $id): ?Model { return $this->model->find($id); }
    public function paginate(int $perPage = 20) { return $this->model->paginate($perPage); }
    // create/update/delete...
}

Then use constructor injection and interface bindings in a service provider — the same shape, but PHP 8+, typed, tested, and yours. You get the design without inheriting the abandonment.

Connection resolution. If the package resolves connections dynamically (that's one of its advertised features), use it only when you genuinely run multi-database apps — e.g., a read replica or a tenant-per-database setup. For single-connection apps, leave the default alone; overriding connection resolution without a need adds an invisible variable to every query.

Gotchas and Tips

  • Alpha tag is a hard gate. composer require without @alpha (or minimum-stability: dev) will fail with a confusing "could not find a matching version" error. That's the tag, not the package name.
  • Namespace is a warning, not a detail. GrahamDeprecated/* in the repo path is the maintainer explicitly signalling archival status. Treat any bug you find as permanently yours; there is no upstream to file against.
  • Service-provider order matters. Register the package provider before your own RepositoryServiceProvider; otherwise the base class bindings may not exist when your bindings are evaluated.
  • Mass assignment will bite you. The base create/update helpers almost certainly delegate to Eloquent's fill, so $fillable/$guarded on the model is your only protection. Never pass Input::all() straight into create() on a model with a permissive $guarded = [].
  • Silent query divergence. A repository wrapper can quietly differ from the Eloquent call you'd have written by hand (default ordering, soft-delete scoping, eager-load defaults). When results look "slightly wrong," compare the wrapper's query to the raw one — enable DB::listen() and log the SQL.
  • Provider name/namespace mismatches. The README is minimal; if the app boots to a "class not found" error, verify the FQCN character-by-character against src/ and check the autoload standard (PSR-0 vs PSR-4) in composer.json.
  • Cache invalidation is on you. Cache-aware reads don't invalidate themselves on writes unless the package explicitly pairs them. If you cache find(), call the invalidator in update()/delete() — this is the classic stale-read source, and it's easy to miss because the reads look fine in dev.
  • Don't composer update. This package pins illuminate/* to the 4.2 line and PHP to 5.x. A blanket update will either fail resolution or drag unrelated packages backwards. Pin and update surgically.
  • Extension points are subclass methods, not config. The right way to customise behaviour is to override a method on your repository subclass or inject a model/connection through the constructor — not to edit the package in vendor/. If you find yourself editing vendor/, you're already better off reimplementing the class.
  • Zero dependents means zero Stack Overflow answers. When you hit a bug, read the source; don't search. Budget accordingly — the ramp-up cost is really the cost of recalling PHP 5.x and L4.2 conventions, not the package itself.
  • Do not adopt this on a new project. The pattern is worth stealing; the dependency is not. If a live L4.2 app depends on it, the real remediation item is the framework version, not this package.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect