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

Controller Laravel Package

smorken/controller

A Laravel package by Smorken that provides a reusable base controller with conventions and helpers to reduce boilerplate for common CRUD, validation, and response-handling tasks in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install from VCS (this is not on Packagist). Add the Bitbucket repo to composer.json and require a pinned ref:

"repositories": [
  { "type": "vcs", "url": "https://bitbucket.org/scott_morken/controller.git" }
]
composer require smorken/controller:dev-master

Then immediately pin the commit in composer.lock, commit the lock file, and note the SHA in your README. There are no tags and no SemVer guarantees — dev-master today is not dev-master next month.

2. Read the source before you read anything else. There is no meaningful README or docs; the src/ directory is the documentation. Budget 30–60 minutes to read every trait top to bottom and answer:

  • What is the exact namespace and trait name(s)?
  • What does it assume about the host controller ($model property? abstract model() method? route parameter names? view name conventions?)
  • Which methods does it provide, which are protected, and which are meant to be overridden?
  • Does it declare authorize, validate, dispatch, or any other method that collides with AuthorizesRequests / ValidatesRequests / DispatchesJobs?
  • What Laravel and PHP versions does the composer.json require block claim?

3. Confirm it loads. In php artisan tinker:

class_uses(App\Http\Controllers\SomeController::class);
method_exists(App\Http\Controllers\SomeController::class, 'index');

If the trait isn't in that list, the autoload or namespace is wrong — fix that before writing any application code.

4. First use case: one resource controller behind a branch. Do not touch the base controller. Pick a single, non-critical CRUD resource, apply the trait, wire the Route::resource(...) declaration, and run the existing feature tests (or write them). Confirm the standard index/show/store/update/destroy verbs behave identically to your current hand-written controller. Keep the branch open until you have at least one test per trait-provided method.

Implementation Patterns

Per-controller use, not base-controller use. Applying the mixin to App\Http\Controllers\Controller gives every controller the helpers, but it also means a future trait method silently shadows something you add later, and it makes the dependency invisible. Apply it explicitly on the controllers that need it so grep -r "use .*Resourceful" tells you the whole blast radius when you eventually remove the package.

Thin controller, explicit model binding. The idiomatic shape is:

class PostController extends Controller
{
    use Resourceful;

    protected $model = Post::class;
}

Whatever discovery mechanism the trait actually uses ($model property, model() method, container binding), set that up first, then keep your Route::resource('posts', PostController::class) declarations conventional. Route parameter names ({post} → Post $post) must match what the trait expects; a mismatch shows up as ModelNotFoundException, not a helpful error message.

Use aliasing for partial overrides. When one action diverges (custom validation, a different redirect), alias the trait method rather than copy-pasting the body:

use Resourceful { store as protected storeBase; }

public function store(Request $request)
{
    $request->validate([
        'title' => 'required|string|max:255',
    ]);

    return $this->storeBase($request);
}

This keeps the upstream behaviour intact for everything you don't override, and makes future comparison against a forked version trivial.

Layer Laravel-native concerns outside the trait. Don't let the mixin be your validation or authorization story. Put FormRequest classes and Policy methods in place as you normally would, and let the trait only handle the controller wiring. This keeps the security-critical logic in first-class Laravel constructs rather than in code you can't audit, and means removing the package later is a mechanical change rather than a rewrite.

Centralise shared view data once. If the package exposes a "view data" or "response payload" hook, override it on your own App\Http\Controllers\Controller and call the trait's version through an alias. That gives you one seam for flash messages, navigation state, and breadcrumbs, and one place to change when the package is removed.

Treat it as a scaffold, not a foundation. The realistic adoption model for a package with no dependents and no tests is: use it in the branch, prove the shape works, then vendor the relevant trait into App\Http\Controllers\Concerns\ with your own tests. The trait is small enough that this is a day's work, and it converts an unowned dependency into owned code.

Gotchas and Tips

Composer will bite you eventually. A VCS repo on Bitbucket with no tags means: CI needs Bitbucket credentials, composer update will happily jump commits on dev-master, and a Bitbucket outage or permission change breaks every fresh install. Mitigations: pin an exact SHA in composer.lock, mirror the repository to your own GitHub/GitLab org, and consider committing the vendored trait into the application instead of depending on the package at all.

Trait method collisions are fatal and only surface at class load. The stock Controller uses AuthorizesRequests, ValidatesRequests, and often DispatchesJobs. If the mixin defines authorize, validate, dispatch, or anything close, PHP throws a fatal error the first time the controller is instantiated — sometimes only in the code path that hits that controller. Resolve collisions up front in the use block with insteadof / as:

use Resourceful, AuthorizesRequests {
    Resourceful::authorize insteadof AuthorizesRequests;
}

Better: rename with as and call both explicitly rather than silently picking a winner.

Undocumented lifecycle assumptions. Controller mixins frequently assume things like $this->middleware(...) calls in a constructor, route-model binding having already resolved, or a particular response shape (view() vs redirect() vs JsonResponse). Test both a web and an API route against the trait — the behaviour may diverge, and an unmaintained package will not tell you which is "correct".

Route caching catches trait-level closure middleware. If the trait registers middleware via closures in the constructor, php artisan route:cache in production will fail or silently drop them. Run php artisan route:cache && php artisan route:clear as part of your deploy test before shipping.

Test coverage is your responsibility, full stop. Zero stars, zero dependents, no visible CI. Write feature tests for every trait-provided action on at least one controller before you ship. These tests double as the regression suite if you later vendor or replace the trait.

Extension points are whatever protected methods exist. The trait's protected methods are the extension API — there is no documented contract. Reading them is how you discover where to hook in. If a method you need to override is private, you cannot override it; either fork or don't use the trait for that controller.

Exit plan from day one. Decide up front how you would remove the package: which controllers use the trait, which overrides exist, which tests cover the trait-provided behaviour. If that list can't be written down, adoption scope is too broad. The realistic exit is "copy the trait into app/Http/Controllers/Concerns/, change the use statement, delete the Composer entry" — verify that works in the branch before you merge.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle