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

Laravel Make Service Laravel Package

getsolaris/laravel-make-service

A Laravel package that adds Artisan commands for generating service classes, helping you organize business logic into dedicated services with a clean, customizable structure.

View on GitHub
Deep Wiki
Context7

Getting Started

getsolaris/laravel-make-service is a small code-generation package: it registers an Artisan command in the make:* family that scaffolds a service class for you, so you stop hand-creating app/Services/*.php boilerplate. Treat it as a developer-experience tool, not a framework feature — it writes a file and gets out of the way.

Install

composer require --dev getsolaris/laravel-make-service

Installing with --dev is the right default for a generator: the command is useful locally and in CI, but you don't want it in a --no-dev production build. Package auto-discovery registers the service provider, so no manual config/app.php edit is normally required.

Where to look first

  1. php artisan list make — confirm the command is registered and read its real signature before trusting any blog post (including this one).
  2. php artisan make:service --help — flags and namespace defaults differ between minor releases.
  3. vendor/getsolaris/laravel-make-service/src/ — the command class plus its stub. The stub is the single best source of truth for what you'll actually get, and it's the file you'd publish/override if you want a different skeleton.

First use case

Pull one meaningful chunk of logic out of a controller. If your InvoiceController@store validates, charges a card, writes the invoice, and fires an event, generate InvoiceService and move the charging and persistence into it. That is exactly the granularity this tool is built for — one class, one collaborator, called from a thin controller.

Note on requirements: v1.1.4 adds Laravel 13.x compatibility. If you're on Laravel 11 or 12, the previous constraint line still works, so don't feel forced to upgrade the framework to adopt this release.

Implementation Patterns

Controller → Service → Model/Client

The dominant pattern. Keep the controller responsible for HTTP concerns only (authorization, validation via a Form Request, response shaping) and let the service own the operation:

public function store(StoreInvoiceRequest $request, InvoiceService $invoices)
{
    $invoice = $invoices->createFor($request->user(), $request->validated());

    return redirect()->route('invoices.show', $invoice);
}

Constructor injection into the controller works without any binding because Laravel's container resolves concrete classes automatically. Only reach for app() inside a service if you're dealing with genuinely dynamic resolution — it makes the class harder to test.

Namespaced generation

Generate into sub-namespaces as your app/Services directory grows. Most make:* commands accept forward-slash notation, which creates nested directories and the matching namespace:

php artisan make:service Billing/StripeCharger
php artisan make:service Reporting/RevenueReportBuilder

If the command rejects slashes in your version, fall back to make:service StripeCharger plus a manual mv — the value is the stub, not the path handling.

Interface + binding

When a service has more than one implementation (real vs. fake, or two payment providers), generate the concrete class and hand-write the interface, then bind it in a ServiceProvider:

$this->app->bind(Charger::class, StripeCharger::class);

This package does not generate or register interfaces for you — that's deliberate scope, not an omission. Type-hint the interface in consumers so tests can swap in a fake via $this->app->instance(...).

Services as the seam for testing

The biggest day-to-day payoff is testability. Once the logic lives in a service, you test it directly, with no HTTP layer:

Http::fake(['api.stripe.com/*' => Http::response(['id' => 'ch_123'], 200)]);

$invoice = app(StripeCharger::class)->charge($user, 2500);

$this->assertDatabaseHas('invoices', ['charge_id' => 'ch_123']);

Reuse across entry points

A service written for a controller is immediately callable from a queued job, an Artisan command, or a scheduled task. That reuse is the argument for the layer in the first place — if a service is only ever called from one controller method, you've added indirection without buying anything.

Gotchas and Tips

Read the actual signature before scripting it. Flags like --force, --interface, or a custom namespace option are not guaranteed across versions. Run --help and check the command class in vendor/ if you plan to call it from a Composer script or CI step.

Overwriting is silent-ish. Most generators refuse to overwrite an existing class unless forced. Don't reflexively add --force to a script — it will happily destroy hand-edited output.

Stubs drift from your conventions. The generated class won't match your house style (strict types, final classes, docblocks). Publish or copy the stub and adapt it once, rather than reformatting every generated file. Check whether the package supports vendor:publish for stubs; if not, the pragmatic route is a small local wrapper command.

No automatic interface binding. Generating a service does not touch your container. If you type-hint an interface that has no binding, you'll get a Target [X] is not instantiable error at runtime, not at generation time. Bind it in a provider and add a test that resolves it.

Keep services stateless. The container resolves a service once per request and reuses it within that scope. Storing per-request state on $this (a user, a request object, an accumulated total) will produce confusing bugs the moment the service is called twice. Pass everything through method arguments, or return a new value object.

Don't inject Request into services. It couples the class to HTTP and makes it awkward to call from jobs and commands — precisely the reuse you installed this package for. Take the specific values you need.

Upgrading to v1.1.4. This release is a compatibility-broadening change (Laravel 13.x support), so it is not a breaking change for existing consumers. Update the single package rather than the whole tree:

composer update getsolaris/laravel-make-service --with-dependencies

Then run php artisan list make once to confirm the provider still boots and the command is discovered — a cheap smoke test that catches autoload or discovery issues immediately. If you're deploying with --no-dev, remember the command is absent in production; any deploy script that shells out to make:service will fail there, which is almost always the desired behaviour.

This package doesn't decide your architecture. It generates a class. It won't tell you whether a service, an action, or a plain method on the model is the right unit. Keep services thin and single-purpose; if a generated service grows past a few public methods, that's a signal to split it, not to reach for more scaffolding.

Naming collisions. make:service can happily produce a class that shadows an existing model or job name in a different namespace. Grep for the class name before generating, especially in flat app/Services setups.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
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