Essentials
Controllers
Organize request handling logic with BaseController
In the API skeleton, application controllers live in app/Controllers/ and usually extend Glueful\Controllers\BaseController.
Basic Controller
<?php
declare(strict_types=1);
namespace App\Controllers;
use Glueful\Controllers\BaseController;
use Glueful\Http\Response;
use Symfony\Component\HttpFoundation\Request;
class UserController extends BaseController
{
public function index(Request $request): Response
{
$users = $this->db->table('users')->get();
return $this->success($users);
}
}
What BaseController Gives You
BaseController already includes:
$this->dbfor database access$this->requestfor the current Symfony request- response helpers like
$this->success()and$this->created() - request helpers like
$this->getRequestData() - lightweight validation via
$this->validateRequest()
Create / Update Example
class TaskController extends BaseController
{
public function store(Request $request): Response
{
$data = $this->getRequestData();
if ($error = $this->validateRequest($data, [
'title' => 'required|max:255',
'description' => 'max:1000',
])) {
return $error;
}
$taskId = $this->db->table('tasks')->insert([
'title' => $data['title'],
'description' => $data['description'] ?? null,
]);
return $this->created([
'id' => $taskId,
'title' => $data['title'],
]);
}
}
Constructor Injection
Controllers are resolved from the container, so constructor injection works:
use Psr\Log\LoggerInterface;
class UserController extends BaseController
{
public function __construct(
\Glueful\Bootstrap\ApplicationContext $context,
private LoggerInterface $logger
) {
parent::__construct($context);
}
public function index(Request $request): Response
{
$this->logger->info('Listing users');
return $this->success($this->db->table('users')->get());
}
}
If you override the constructor, call parent::__construct($context) so the base dependencies are initialized.
ResourceController
Glueful also ships a built-in Glueful\Controllers\ResourceController for generic CRUD-heavy cases. Use it when you want convention-driven resource endpoints quickly, but prefer explicit controllers first while you are learning the framework.
For most new applications, start with explicit controllers in app/Controllers and move to generic resource wiring only when the tradeoff is clear.