Installation
composer require alexandre-mace/sniffer
Ensure your project uses PHP 7.1+ and Symfony 4.4.x components (HTTP Foundation, Kernel, Validator, Serializer).
First Use Case: Extracting and Validating a Request DTO
use AlexandreMace\Sniffer\Sniffer;
// Initialize Sniffer with a request object
$sniffer = new Sniffer($request);
// Extract a DTO class from a request (e.g., JSON payload)
$dto = $sniffer->extract('App\DTO\MyRequestDTO');
// Validate the extracted DTO
$errors = $sniffer->validate($dto);
if ($errors->count() > 0) {
// Handle validation errors
}
Key Files to Review
src/Sniffer.php: Core class for extraction and validation.tests/: Unit tests for expected behavior (e.g., SnifferTest.php).composer.json: Dependencies and constraints.Middleware Integration Use the Sniffer in middleware to validate incoming requests early:
use AlexandreMace\Sniffer\Sniffer;
use Symfony\Component\HttpFoundation\Request;
public function handle(Request $request, Closure $next)
{
$sniffer = new Sniffer($request);
$dto = $sniffer->extract('App\DTO\UserCreateDTO');
if ($sniffer->validate($dto)->count() > 0) {
return response()->json(['errors' => $sniffer->getErrors()], 400);
}
return $next($request);
}
DTO Design Patterns
DTO (e.g., UserCreateDTO).@Assert\NotBlank()).Serializable or use #[SerializedName] for custom field mapping.Integration with Symfony Components
config/packages/serializer.yaml:
framework:
serializer:
mapping:
paths: ['%kernel.project_dir%/config/serializer']
config/validator/validation.yaml.Command-Line Usage For testing or bulk validation:
$sniffer = new Sniffer($request);
$dto = $sniffer->extract('App\DTO\ReportDTO');
$errors = $sniffer->validate($dto);
// Log or export errors (e.g., to a file)
file_put_contents('validation_errors.log', print_r($errors, true));
Dependency Conflicts
4.4.*. If your project uses a different version (e.g., Symfony 5/6), conflicts may arise.composer why-not to diagnose conflicts or override dependencies in composer.json:
"extra": {
"symfony-require": "4.4.*"
}
DTO Class Not Found
extract() fails with ClassNotFoundException, ensure:
composer dump-autoload).App\DTO\MyDTO, not DTO\MyDTO).Validation Errors Not Triggering
$sniffer->validate() returns no errors, verify:
@Assert\Type("string")).Performance Overhead
Enable Debug Mode Temporarily enable Symfony’s debug mode to inspect validation errors:
$sniffer->setDebug(true);
Log Raw Data Dump the extracted DTO or request data for debugging:
\Symfony\Component\VarDumper\VarDumper::dump($dto);
Custom Error Handling Override error formatting:
$errors = $sniffer->validate($dto);
foreach ($errors as $error) {
logger()->error("Validation failed: {$error->getMessage()}");
}
Custom Validators Extend the Sniffer to support custom validation logic:
class CustomSniffer extends Sniffer
{
public function validate($dto, array $customRules = [])
{
// Add custom rules before/after Symfony validation
$errors = parent::validate($dto);
foreach ($customRules as $rule) {
if (!$rule($dto)) {
$errors->addViolation(new \Symfony\Component\Validator\ConstraintViolation(
'Custom rule failed',
null,
[],
$dto,
'custom_rule',
null
));
}
}
return $errors;
}
}
Event Dispatching Trigger events before/after extraction or validation:
use Symfony\Component\EventDispatcher\EventDispatcher;
$dispatcher = new EventDispatcher();
$sniffer = new Sniffer($request, $dispatcher);
// Listen for events
$dispatcher->addListener('sniffer.extract', function ($event) {
logger()->info('DTO extracted', ['dto' => $event->getDto()]);
});
Configuration Overrides Override default behavior via constructor options:
$sniffer = new Sniffer($request, [
'serializer_groups' => ['default', 'custom_group'],
'validation_groups' => ['registration', 'default'],
]);
config/serializer/mapping.yaml:
App\DTO\UserDTO:
properties:
email:
groups: [registration, default]
$sniffer->getSerializer()->enableMaxDepthChecks(false);
How can I help you explore Laravel packages today?