> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doman.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Admin controller guide en

# AdminController Extension Guide

## Overview

The `AdminController` is a powerful base controller that provides CRUD operations, menu management, and standardized responses for admin interfaces. This guide covers how to create new controllers that extend `AdminController`.

## Quick Start

### Basic Controller Structure

```php theme={null}
<?php

namespace App\Http\Controllers\YourNamespace;

use App\Http\Controllers\Core\AdminController;
use App\Models\YourNamespace\YourModel;
use Illuminate\Http\Request;

class YourController extends AdminController
{
    public function __construct()
    {
        // Set required properties
        $this->modelClass = YourModel::class;
        $this->entity = 'YourEntity';
        $this->namespace = 'YourNamespace';
        
        // Call parent constructor AFTER setting properties
        parent::__construct();
        
        // Configure controller-specific settings
        $this->setupController();
    }
    
    private function setupController()
    {
        // Configure Inertia page paths
        $this->inertia_page_index = 'YourNamespace/YourEntity/Index';
        $this->inertia_page_create = 'YourNamespace/YourEntity/Create';
        $this->inertia_page_edit = 'YourNamespace/YourEntity/Edit';
        $this->inertia_page_view = 'YourNamespace/YourEntity/View';
        
        // Configure routes
        $this->controller_base_route = 'your-namespace.your-entity';
        $this->controller_index_route = 'your-namespace.your-entity.index';
        
        // Configure search and sort fields
        $this->searchable_fields = ['name', 'email', 'description'];
        $this->sortable_fields = ['created_at', 'updated_at', 'name'];
        
        // Configure validation rules
        $this->setupValidation();
    }
}
```

## Required Properties

### Essential Properties (Must Set)

```php theme={null}
protected string $modelClass = '';     // Fully qualified model class name
protected string $entity = '';         // Entity name for messages/defaults
protected string $namespace = '';      // Controller namespace for organization
```

### Inertia Page Configuration

```php theme={null}
protected string $inertia_page_index = '';   // e.g., 'Directory/Member/Index'
protected string $inertia_page_create = '';  // e.g., 'Directory/Member/Create'
protected string $inertia_page_edit = '';    // e.g., 'Directory/Member/Edit'
protected string $inertia_page_view = '';    // e.g., 'Directory/Member/View'
```

### Route Configuration

```php theme={null}
protected string $controller_base_route = '';    // e.g., 'directory.member'
protected string $controller_index_route = '';   // e.g., 'directory.member.index'
```

## Optional Configuration Properties

### Search & Filter Configuration

```php theme={null}
protected array $searchable_fields = [];   // Fields for global search
protected array $sortable_fields = [];     // Fields allowed for sorting
protected array $filter_casts = [];        // Type casting for filters
```

**Example**:

```php theme={null}
$this->searchable_fields = ['name', 'email', 'phone', 'address'];
$this->sortable_fields = ['created_at', 'updated_at', 'name', 'email'];
$this->filter_casts = [
    'status' => 'boolean',
    'age' => 'integer',
    'salary' => 'float'
];
```

### Validation Rules

```php theme={null}
protected array $validator_create = [];    // Rules for creating records
protected array $validator_update = [];    // Rules for updating records
```

**Example**:

```php theme={null}
private function setupValidation()
{
    $this->validator_create = [
        'name' => 'required|string|max:255|unique:members,name',
        'email' => 'required|email|unique:members,email',
        'phone' => 'nullable|string|max:20',
    ];
    
    $this->validator_update = [
        'name' => 'required|string|max:255|unique:members,name,' . $this->request_id,
        'email' => 'required|email|unique:members,email,' . $this->request_id,
        'phone' => 'nullable|string|max:20',
    ];
}
```

### Pagination & Display

```php theme={null}
protected int $per_page = 15;                        // Items per page
protected string $data_view_default = 'table';       // Default view type
protected array $extra_props = [];                   // Additional props for views
```

### Authorization

```php theme={null}
protected string $auth_entity = '';    // Authorization entity name
```

**Example**:

```php theme={null}
$this->auth_entity = 'all-members';
```

## Method Overrides

### Query Modification

Override this method to add custom query logic:

```php theme={null}
public function additionalQuery(Request $request, $query, ?string $type = null)
{
    if ($type === 'index') {
        // Add eager loading for index
        $query->with(['category', 'tags']);
        
        // Add custom filters
        if ($request->filled('category_id')) {
            $query->where('category_id', $request->category_id);
        }
    }
    
    if ($type === 'view' || $type === 'edit') {
        // Add more detailed relationships for single item views
        $query->with(['category', 'tags', 'reviews.user']);
    }
    
    return $query;
}
```

### Page-Specific Customization

```php theme={null}
public function index(Request $request)
{
    // Set page-specific data
    $this->data_object_extra = [
        'totalActive' => $this->model->where('status', 'active')->count(),
        'statistics' => $this->calculateStatistics(),
    ];
    
    // Set breadcrumbs
    $this->breadcrumbs = [
        ['title' => 'Dashboard', 'href' => route('main.dashboard.index')],
        ['title' => 'Your Section', 'href' => route('your.section.index')],
        ['title' => 'Your Entity List', 'href' => route($this->controller_index_route)],
    ];
    
    return parent::index($request);
}

public function create(Request $request)
{
    // Add form options
    $this->extra_props['categories'] = Category::orderBy('name')->get(['id', 'name']);
    $this->extra_props['statuses'] = ['active', 'inactive', 'pending'];
    
    return parent::create($request);
}
```

### Form Options Setup

```php theme={null}
public function setupFormOptions(Request $request, $formOptions, $data = null)
{
    // Add dynamic form options based on current data or request
    $formOptions['categories'] = Category::where('active', true)
                                        ->orderBy('name')
                                        ->get(['id', 'name']);
    
    if ($data && isset($data['category_id'])) {
        $formOptions['subcategories'] = Subcategory::where('category_id', $data['category_id'])
                                                   ->get(['id', 'name']);
    }
    
    return $formOptions;
}
```

## Lifecycle Hooks

### Create Hooks

```php theme={null}
protected function beforeStore(Request $request, array $validatedData): array
{
    // Modify data before storing
    $validatedData['user_id'] = auth()->id();
    $validatedData['slug'] = Str::slug($validatedData['name']);
    
    return $validatedData;
}

protected function afterStore(Request $request, Model $instance): void
{
    // Perform actions after storing
    // Log activity
    activity('created')
        ->performedOn($instance)
        ->withProperties($instance->toArray())
        ->log('Created new ' . $this->entity);
    
    // Send notifications
    // Cache clearing
    // etc.
}
```

### Update Hooks

```php theme={null}
protected function beforeUpdate(Request $request, array $validatedData, Model $instance): array
{
    // Store original data for comparison
    $this->original_data = $instance->getOriginal();
    
    // Modify data before updating
    if (isset($validatedData['name']) && $validatedData['name'] !== $instance->name) {
        $validatedData['slug'] = Str::slug($validatedData['name']);
    }
    
    return $validatedData;
}

protected function afterUpdate(Request $request, Model $instance): void
{
    // Log changes
    $changes = $instance->getChanges();
    if (!empty($changes)) {
        activity('updated')
            ->performedOn($instance)
            ->withProperties([
                'old' => $this->original_data,
                'new' => $changes
            ])
            ->log('Updated ' . $this->entity);
    }
}
```

### Delete Hooks

```php theme={null}
protected function beforeDestroy(Request $request, Model $instance): void
{
    // Check for dependencies
    if ($instance->children()->count() > 0) {
        throw new \Exception('Cannot delete item with child records');
    }
    
    // Backup data
    $this->backup_data = $instance->toArray();
}

protected function afterDestroy(Request $request, Model $instance): void
{
    // Clean up related data
    // Log deletion
    activity('deleted')
        ->withProperties($this->backup_data)
        ->log('Deleted ' . $this->entity);
}
```

## Menu Configuration

### Top Menu Level Control

```php theme={null}
public function index(Request $request)
{
    // Control which level of menu to show in top navigation
    $this->generateTopMenu(1); // Show children of active group (default)
    // $this->generateTopMenu(0); // Show main groups instead
    
    return parent::index($request);
}
```

## Advanced Features

### Custom Actions

```php theme={null}
public function customAction(Request $request, $id)
{
    $item = $this->model->findOrFail($id);
    
    // Perform custom logic
    $result = $this->performCustomOperation($item);
    
    $message = $result ? 'Operation completed successfully' : 'Operation failed';
    $type = $result ? 'success' : 'error';
    
    return redirect()
        ->route($this->controller_index_route)
        ->with($type, $message);
}
```

### Modal Support

```php theme={null}
public function index(Request $request)
{
    // Handle modal requests
    if ($request->filled('modal') && $request->filled('item_id')) {
        $modalType = $request->input('modal');
        $itemId = $request->input('item_id');
        
        switch ($modalType) {
            case 'show-details':
                $this->extra_props['modalData'] = $this->model
                    ->with(['relations'])
                    ->findOrFail($itemId);
                break;
        }
    }
    
    return parent::index($request);
}
```

## Complete Example

```php theme={null}
<?php

namespace App\Http\Controllers\Directory;

use App\Http\Controllers\Core\AdminController;
use App\Models\Directory\Member;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class MemberController extends AdminController
{
    public function __construct()
    {
        // Required properties
        $this->modelClass = Member::class;
        $this->entity = 'Member';
        $this->namespace = 'Directory';
        
        // Must call parent constructor after setting required properties
        parent::__construct();
        
        // Configure controller
        $this->setupController();
    }
    
    private function setupController()
    {
        // Inertia pages
        $this->inertia_page_index = 'Directory/Member/Index';
        $this->inertia_page_create = 'Directory/Member/Create';
        $this->inertia_page_edit = 'Directory/Member/Edit';
        $this->inertia_page_view = 'Directory/Member/View';
        
        // Routes
        $this->controller_base_route = 'directory.member';
        $this->controller_index_route = 'directory.member.index';
        
        // Authorization
        $this->auth_entity = 'all-members';
        
        // Search & sort configuration
        $this->searchable_fields = ['name', 'email', 'phone', 'address'];
        $this->sortable_fields = ['created_at', 'updated_at', 'name', 'email'];
        
        // Validation
        $this->validator_create = [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:members,email',
            'phone' => 'nullable|string|max:20',
        ];
        
        $this->validator_update = [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:members,email,' . $this->request_id,
            'phone' => 'nullable|string|max:20',
        ];
    }
    
    public function additionalQuery(Request $request, $query, ?string $type = null)
    {
        if ($type === 'index') {
            $query->with(['category', 'status']);
        }
        
        return $query;
    }
    
    public function index(Request $request)
    {
        $this->data_object_extra = [
            'totalMembers' => Member::count(),
            'activeMembers' => Member::where('status', 'active')->count(),
        ];
        
        $this->breadcrumbs = [
            ['title' => 'Dashboard', 'href' => route('main.dashboard.index')],
            ['title' => 'Directory', 'href' => route('directory.dashboard.index')],
            ['title' => 'Member List', 'href' => route($this->controller_index_route)],
        ];
        
        return parent::index($request);
    }
}
```

## Best Practices

1. **Always call `parent::__construct()`** after setting required properties
2. **Set breadcrumbs** in each page method for better navigation
3. **Use lifecycle hooks** for complex business logic
4. **Configure search and sort fields** for better user experience
5. **Add proper validation rules** for data integrity
6. **Use consistent naming conventions** for routes and pages
7. **Handle authorization** through the auth\_entity property
8. **Add meaningful extra\_props** for enhanced UI functionality
