Skip to content

Web Controller

BaseWebController provides Blade/web endpoints. Returns View and RedirectResponse with flash messages.

Constructor

php
use Anil\FastApiCrud\Http\Controllers\BaseWebController;

class PostController extends BaseWebController
{
    public function __construct()
    {
        parent::__construct(
            model: Post::class,
            storeRequest: StorePostRequest::class,
            updateRequest: UpdatePostRequest::class,
            viewPrefix: 'admin.posts',     // View name prefix
            routePrefix: 'admin.posts',    // Route name prefix for redirects
            resourceName: 'post',          // Variable name in show/edit views
            collectionName: 'posts',       // Variable name in index view
            resource: PostResource::class, // Optional — for data transformation
        );
    }
}
ParameterTypeRequiredDescription
modelclass-string<Model>YesEloquent model class
storeRequestclass-string<FormRequest>YesStore validation
updateRequestclass-string<FormRequest>YesUpdate validation
viewPrefixstringYese.g. 'admin.posts' resolves to admin.posts.index
routePrefixstringYese.g. 'admin.posts' redirects to route('admin.posts.index')
resourceNamestringYesVariable name for single model in views
collectionNamestringYesVariable name for paginated collection in index
resourceclass-string<JsonResource>|nullNoOptional resource for data transformation

Methods

MethodHTTPReturnView/Route
index()GETView{viewPrefix}.index
create()GETView{viewPrefix}.create
store()POSTRedirectResponseRedirect to {routePrefix}.index
show($id)GETView{viewPrefix}.show
edit($id)GETView{viewPrefix}.edit
update($id)PUTRedirectResponseRedirect to {routePrefix}.index
destroy($id)DELETERedirectResponseRedirect to {routePrefix}.index
delete()POSTRedirectResponseRedirect to {routePrefix}.index
changeStatus($id, $column)PUTRedirectResponseRedirect to {routePrefix}.index
updateColumn($id, $column)PUTRedirectResponseRedirect to {routePrefix}.index
restore($id)PUTRedirectResponseRedirect to {routePrefix}.index
restoreAll()POSTRedirectResponseRedirect to {routePrefix}.index
permanentDelete($id)POSTRedirectResponseRedirect to {routePrefix}.index

View Variables

ViewVariableType
index${collectionName} (e.g. $posts)Paginated collection
show${resourceName} (e.g. $post)Model instance
edit${resourceName} (e.g. $post)Model instance
create(none by default)Override to pass data

Flash Messages

All write operations redirect with a flash message. Override any message method:

php
class PostController extends BaseWebController
{
    protected function storeSuccessMessage(): string       { return __('Post created!'); }
    protected function updateSuccessMessage(): string      { return __('Post updated!'); }
    protected function destroySuccessMessage(): string     { return __('Post deleted.'); }
    protected function bulkDeleteSuccessMessage(): string  { return __('Posts deleted.'); }
    protected function statusChangeSuccessMessage(): string    { return __('Status updated.'); }
    protected function columnUpdateSuccessMessage(): string    { return __('Column updated.'); }
    protected function restoreSuccessMessage(): string         { return __('Post restored.'); }
    protected function restoreAllSuccessMessage(): string      { return __('All posts restored.'); }
    protected function permanentDeleteSuccessMessage(): string { return __('Post permanently deleted.'); }
}

Flash session keys are configurable via fast-api.web.flash_key_success and fast-api.web.flash_key_error.

On error, redirectBackWithError() redirects back with old input and an error flash message.

Overriding Views

Override any method to pass extra data:

php
class PostController extends BaseWebController
{
    public function create(): \Illuminate\View\View
    {
        return view($this->viewName('create'), [
            'categories' => Category::all(),
            'tags' => Tag::all(),
        ]);
    }

    public function edit(int|string $id): \Illuminate\View\View
    {
        $query = $this->buildShowQuery();

        return view($this->viewName('edit'), [
            $this->resourceName => $query->findOrFail($id),
            'categories' => Category::all(),
        ]);
    }
}

The viewName(string $suffix) helper resolves the full view name from the prefix.

Blade Example

blade
{{-- resources/views/admin/posts/index.blade.php --}}
@extends('layouts.app')

@section('content')
<div class="container">
    @if(session('success'))
        <div class="alert alert-success">{{ session('success') }}</div>
    @endif

    @if(session('error'))
        <div class="alert alert-danger">{{ session('error') }}</div>
    @endif

    <div class="d-flex justify-content-between mb-3">
        <h1>Posts</h1>
        <a href="{{ route('admin.posts.create') }}" class="btn btn-primary">
            Create Post
        </a>
    </div>

    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Status</th>
                <th>Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach($posts as $post)
                <tr>
                    <td>{{ $post->id }}</td>
                    <td>{{ $post->name }}</td>
                    <td>{{ $post->status ? 'Active' : 'Inactive' }}</td>
                    <td>
                        <a href="{{ route('admin.posts.show', $post) }}">View</a>
                        <a href="{{ route('admin.posts.edit', $post) }}">Edit</a>
                        <form action="{{ route('admin.posts.destroy', $post) }}"
                              method="POST" class="d-inline">
                            @csrf
                            @method('DELETE')
                            <button type="submit" class="btn btn-sm btn-danger"
                                    onclick="return confirm('Are you sure?')">
                                Delete
                            </button>
                        </form>
                    </td>
                </tr>
            @endforeach
        </tbody>
    </table>

    {{ $posts->links() }}
</div>
@endsection

Web Routes

php
// routes/web.php
use App\Http\Controllers\PostController;

// Standard Laravel resource routes
Route::resource('admin/posts', PostController::class);

// Extended operations
Route::patch('admin/posts/{id}/status', [PostController::class, 'changeStatus'])
    ->name('admin.posts.changeStatus');
Route::patch('admin/posts/{id}/restore', [PostController::class, 'restore'])
    ->name('admin.posts.restore');
Route::post('admin/posts/restore', [PostController::class, 'restoreAll'])
    ->name('admin.posts.restoreAll');
Route::delete('admin/posts/{id}/force', [PostController::class, 'permanentDelete'])
    ->name('admin.posts.permanentDelete');

Released under the MIT License.