# Quick Start Guide - New Laravel Architecture

## Adding a New Feature (e.g., Sponsorship Management)

Follow these steps to implement a new feature using the repository/service pattern:

### Step 1: Create the Repository

```php
// app/Repositories/SponsorRepository.php
<?php

namespace App\Repositories;

use App\Models\Sponsor;

class SponsorRepository extends BaseRepository
{
    public function getModel(): string
    {
        return Sponsor::class;
    }

    public function getActive()
    {
        return $this->model->where('is_active', true)->get();
    }
}
```

### Step 2: Create the Service

```php
// app/Services/Sponsor/SponsorService.php
<?php

namespace App\Services\Sponsor;

use App\Repositories\SponsorRepository;
use App\Services\BaseService;

class SponsorService extends BaseService
{
    public function __construct(
        private SponsorRepository $sponsorRepository
    ) {
        $this->repository = $sponsorRepository;
    }

    public function getActiveSponsor()
    {
        return $this->sponsorRepository->getActive();
    }

    public function createSponsor(array $data)
    {
        return $this->sponsorRepository->create($data);
    }
}
```

### Step 3: Create Form Requests

```php
// app/Http/Requests/Sponsor/StoreSponsorRequest.php
<?php

namespace App\Http\Requests\Sponsor;

use Illuminate\Foundation\Http\FormRequest;

class StoreSponsorRequest extends FormRequest
{
    public function authorize(): bool
    {
        return auth()->user()->is_admin;
    }

    public function rules(): array
    {
        return [
            'name' => 'required|string|max:255|unique:sponsors',
            'email' => 'required|email|unique:sponsors',
            'phone' => 'nullable|string|max:20',
            'website' => 'nullable|url',
            'is_active' => 'boolean',
        ];
    }
}
```

### Step 4: Create API Resources

```php
// app/Http/Resources/Sponsor/SponsorResource.php
<?php

namespace App\Http\Resources\Sponsor;

use Illuminate\Http\Resources\Json\JsonResource;

class SponsorResource extends JsonResource
{
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'phone' => $this->phone,
            'website' => $this->website,
            'is_active' => $this->is_active,
            'created_at' => $this->created_at?->toIso8601String(),
        ];
    }
}
```

### Step 5: Create the Controller

```php
// app/Http/Controllers/Api/Sponsor/SponsorController.php
<?php

namespace App\Http\Controllers\Api\Sponsor;

use App\Http\Controllers\Controller;
use App\Http\Requests\Sponsor\StoreSponsorRequest;
use App\Http\Resources\Sponsor\SponsorResource;
use App\Services\Sponsor\SponsorService;

class SponsorController extends Controller
{
    public function __construct(
        private SponsorService $sponsorService
    ) {}

    public function index()
    {
        return response()->json([
            'success' => true,
            'data' => SponsorResource::collection(
                $this->sponsorService->getAll()
            ),
        ]);
    }

    public function store(StoreSponsorRequest $request)
    {
        $sponsor = $this->sponsorService->createSponsor(
            $request->validated()
        );

        return response()->json([
            'success' => true,
            'data' => new SponsorResource($sponsor),
        ], 201);
    }
}
```

### Step 6: Register in ServiceProvider

```php
// In app/Providers/RepositoryServiceProvider.php
use App\Repositories\SponsorRepository;
use App\Services\Sponsor\SponsorService;

public function register(): void
{
    $this->app->bind(SponsorRepository::class, function ($app) {
        return new SponsorRepository();
    });

    $this->app->bind(SponsorService::class, function ($app) {
        return new SponsorService(
            $app->make(SponsorRepository::class)
        );
    });
}
```

### Step 7: Add Routes

```php
// routes/api.php
Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('sponsors', SponsorController::class);
});
```

## Common Patterns

### Using Services in Controllers

```php
class LeagueController extends Controller
{
    public function __construct(
        private LeagueService $leagueService
    ) {}

    public function index()
    {
        $leagues = $this->leagueService->getActiveLeagues();
        return LeagueResource::collection($leagues);
    }
}
```

### Using Repositories in Services

```php
public function getLeagueWithStats(int $id)
{
    $league = $this->leagueRepository->findOrFail($id);
    
    return [
        'league' => $league,
        'stats' => $this->leagueRepository->getStats($id),
    ];
}
```

### Using Form Requests for Validation

```php
public function store(StoreLeagueRequest $request)
{
    // Request is already validated
    $league = $this->leagueService->createLeague(
        $request->validated()
    );
    
    return new LeagueResource($league);
}
```

### Using Resources for API Responses

```php
// Always use resources for consistent API responses
return response()->json([
    'success' => true,
    'data' => new LeagueResource($league),
], 201);

// For collections
return response()->json([
    'success' => true,
    'data' => LeagueResource::collection($leagues),
]);
```

### Using Enums for Type Safety

```php
use App\Enums\LeagueStatus;

// Get all statuses
$statuses = LeagueStatus::options();

// Use in queries
$active = League::where('status', LeagueStatus::ACTIVE->value)->get();

// Use in validations
'status' => 'required|in:' . implode(',', array_column(
    LeagueStatus::options(), 
    'value'
))
```

## Testing Your Code

### Testing a Service

```php
<?php

namespace Tests\Unit\Services;

use Tests\TestCase;
use App\Services\League\LeagueService;
use App\Repositories\LeagueRepository;
use Mockery\Mock;

class LeagueServiceTest extends TestCase
{
    private LeagueService $service;
    private Mock $repository;

    protected function setUp(): void
    {
        parent::setUp();
        
        $this->repository = \Mockery::mock(LeagueRepository::class);
        $this->service = new LeagueService($this->repository);
    }

    public function test_can_get_active_leagues()
    {
        $this->repository
            ->shouldReceive('getActive')
            ->once()
            ->andReturn([]);

        $result = $this->service->getActiveLeagues();

        $this->assertIsArray($result);
    }
}
```

## CLI Commands for Creating Boilerplate

You can create Laravel commands to generate new repositories, services, requests, and resources automatically.

```bash
# Example future command (to be implemented)
php artisan make:service-feature {name}
# This would create: Repository, Service, Requests, Resources, Controller
```

## Checklist for New Features

- [ ] Create Repository extending `BaseRepository`
- [ ] Create Service extending `BaseService`
- [ ] Create `StoreXXXRequest` Form Request
- [ ] Create `UpdateXXXRequest` Form Request
- [ ] Create `XXXResource` API Resource
- [ ] Create `XXXController` with dependency injection
- [ ] Register repository and service in `RepositoryServiceProvider`
- [ ] Add routes in `routes/api.php`
- [ ] Write unit tests for service
- [ ] Write feature tests for controller
- [ ] Document in API docs

## Troubleshooting

### Service not found error
- Make sure the service is registered in `RepositoryServiceProvider`
- Check the namespace is correct
- Run `php artisan cache:clear`

### Form Request not validating
- Check the rules array is correct
- Verify authorize() returns true
- Check the field names match the form

### Resource not transforming data
- Ensure you're using `->toArray()` or `->toJson()`
- Check relationship names match the model
- Use `$this->whenLoaded()` for optional relationships

---

**Happy coding! 🚀**
