Validation
This page covers validation of file uploads in your application using the AssetConnectValidator
class. This class works together with the ValidationRuleCollector
to generate validation rules based on asset collection definitions and validate data against these rules.
Overview
The AssetConnectValidator
class provides a flexible way to validate file uploads by:
- Generating validation rules from asset collection definitions
- Supporting validation of multiple fields with different collection definitions
- Providing methods to validate data against these rules
- Supporting validation directly from HTTP requests
Basic Usage
// Get a collection definition
$collectionDefinition = new YourCollectionDefinition();
// Create a validator
$validator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator($collectionDefinition);
// Set a field collection definition (required)
$validator->setFieldCollectionDefinition('file', $collectionDefinition);
// Validate data
$data = [
'file' => $this->request->getFile('upload')
];
if ($validator->validate($data)) {
// Validation passed
// Process the file
} else {
// Validation failed
$errors = $validator->getErrors();
// Handle errors
}
Defining Field Names
You must define field names using the setFieldCollectionDefinition
method:
// Create a validator
$validator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator($collectionDefinition);
// Define a field name
$validator->setFieldCollectionDefinition('upload_file', $collectionDefinition);
// Now your data should use this field name
$data = [
'upload_file' => $this->request->getFile('upload')
];
if ($validator->validate($data)) {
// Validation passed
}
This allows you to have multiple file uploads with different field names.
Using Different Collection Definitions for Different Fields
You can set different collection definitions for different fields using the setFieldCollectionDefinition
method:
// Create a validator
$validator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator(
new DefaultCollectionDefinition()
);
// Set collection definitions for fields
$validator->setFieldCollectionDefinition('file1', new DefaultCollectionDefinition());
$validator->setFieldCollectionDefinition('file2', new DefaultCollectionDefinition());
$validator->setFieldCollectionDefinition('testfile', new NewCollectionDefinition());
// Validate data
$data = [
'file1' => $this->request->getFile('upload1'),
'file2' => $this->request->getFile('upload2'),
'testfile' => $this->request->getFile('test')
];
if ($validator->validate($data)) {
// Validation passed for all fields
// Process the files
} else {
// Validation failed
$errors = $validator->getErrors();
// Handle errors
}
This approach allows you to use a single validator instance for multiple fields, each with its own collection definition.
Validating Specific Fields
You can validate specific fields instead of all fields:
if ($validator->validateFields($data, 'file')) {
// Validation passed for the 'file' field
// Process the file
}
Validating All Defined Fields
After setting up field collection definitions with setFieldCollectionDefinition
, you can validate all defined fields without having to specify them again:
// Create a validator
$validator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator(
new DefaultCollectionDefinition()
);
// Set collection definitions for fields
$validator->setFieldCollectionDefinition('file1', new DefaultCollectionDefinition());
$validator->setFieldCollectionDefinition('file2', new DefaultCollectionDefinition());
$validator->setFieldCollectionDefinition('testfile', new NewCollectionDefinition());
// Validate all defined fields (file1, file2, testfile)
$data = [
'file1' => $this->request->getFile('upload1'),
'file2' => $this->request->getFile('upload2'),
'testfile' => $this->request->getFile('test')
];
if ($validator->validateDefinedFields($data)) {
// Validation passed for all defined fields
// Process the files
} else {
// Validation failed
$errors = $validator->getErrors();
// Handle errors
}
You can also get the names of all defined fields:
$fieldNames = $validator->getDefinedFieldNames(); // Returns ['file1', 'file2', 'testfile']
And get the validation rules for all defined fields:
$definedFieldRules = $validator->getRulesForDefinedFields();
Validating Fields from Request
You can validate fields directly from the request using CodeIgniter's withRequest
method:
if ($validator->validateFieldsFromRequest('file1', 'profilePicture')) {
// Validation passed for 'file1' and 'profilePicture' from the request
// Process the files
}
This method uses CodeIgniter's validation with the request data directly, which simplifies the validation process. It gets the rules for the specified fields and applies them to the request data.
For multiple file uploads, you can still specify the field names as you would with other validation methods:
if ($validator->validateFieldsFromRequest('file1', 'documents')) {
// Validation passed for 'file1' and 'documents' from the request
// Process the files
}
Validating All Defined Fields from Request
Similar to validateDefinedFields
, you can validate all defined fields directly from the request without having to specify them again:
if ($validator->validateDefinedFieldsFromRequest()) {
// Validation passed for all defined fields from the request
// Process the files
} else {
// Validation failed
$errors = $validator->getErrors();
// Handle errors
}
This is particularly useful when you've already defined your fields with setFieldCollectionDefinition
and don't want to repeat the field names when validating.
Getting Validation Rules and Errors
You can get all validation rules or rules for specific fields:
// Get all rules
$allRules = $validator->getRules();
// Get rules for specific fields
$fileRules = $validator->getRulesForFields('file');
// Get rules for all defined fields
$definedFieldRules = $validator->getRulesForDefinedFields();
// Get validation errors
$errors = $validator->getErrors();
The getRules()
method returns CodeIgniter 4 compatible validation rules for the current validator instance. This is particularly useful when you want to combine AssetConnectValidator rules with additional validation rules for other fields in your form and continue validation using CodeIgniter 4's validator.
Example: Combining with CodeIgniter 4 Validator
// Create AssetConnectValidator and set up rules for file uploads
$fileValidator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator();
$fileValidator->setFieldCollectionDefinition('profile_image', new ProfileImageCollection());
// Get the rules generated by AssetConnectValidator
$fileRules = $fileValidator->getRules();
// Create a standard CodeIgniter validator with additional rules
$validation = \Config\Services::validation();
$validation->setRules([
// Add file upload rules from AssetConnectValidator
...$fileRules,
// Add additional rules for other form fields
'username' => 'required|min_length[5]|max_length[50]',
'email' => 'required|valid_email',
'age' => 'required|integer|greater_than[17]'
]);
// Run validation on all fields together
if ($validation->withRequest($this->request)->run()) {
// All validation passed (both files and other fields)
// Process the form data
} else {
// Validation failed
$errors = $validation->getErrors();
// Handle errors
}
This approach allows you to seamlessly integrate file validation with other form field validations in your application.
Example with a Collection Definition
Here's an example of how validation rules are generated from a collection definition:
class ImagesCollection implements AssetCollectionDefinitionInterface, AssetVariantsInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
$definition
->allowedExtensions(AssetExtension::JPG, AssetExtension::PNG, AssetExtension::GIF)
->allowedMimeTypes(AssetMimeType::IMAGE_JPEG, AssetMimeType::IMAGE_PNG, AssetMimeType::IMAGE_GIF)
->setMaxFileSize(2 * 1024 * 1024) // 2MB
->singleFileCollection();
}
// ... other methods
}
When you set this collection definition for a field, the generated validation rules would be:
// For field name 'image'
[
'image' => 'uploaded[image]|ext_in[image,jpg,png,gif]|mime_in[image,image/jpeg,image/png,image/gif]|max_size[image,2048]|max_file_count[1]'
]
Validating Multiple Fields with Different Collection Definitions
As shown in the previous section, you can use the CollectionValidator
class to validate multiple fields with different collection definitions:
// Create a validator
$validator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator(
new ImagesCollection()
);
// Set collection definitions for fields
$validator->setFieldCollectionDefinition('file1', new ImagesCollection());
$validator->setFieldCollectionDefinition('multipleFileCollection', new DocumentsCollection());
$validator->setFieldCollectionDefinition('profilePicture', new AvatarCollection());
// Validate data
$data = [
'file1' => $this->request->getFile('upload1'),
'multipleFileCollection' => $this->request->getFileMultiple('documents'),
'profilePicture' => $this->request->getFile('avatar')
];
if ($validator->validate($data)) {
// Validation passed for all fields
// Process the files
} else {
// Validation failed
$errors = $validator->getErrors();
// Handle errors
}
You can also validate specific fields:
if ($validator->validateFields($data, 'file1', 'profilePicture')) {
// Validation passed for 'file1' and 'profilePicture'
// Process these files
}
And get rules for specific fields:
$file1Rules = $validator->getRulesForFields('file1');
Legacy Approach: MultiFieldCollectionValidator
For backward compatibility, the MultiFieldCollectionValidator
class is still available, but using the enhanced CollectionValidator
class as shown above is the recommended approach:
// Create a multi-field validator
$multiValidator = new \Maniaba\AssetConnect\Validation\MultiFieldCollectionValidator();
// Add fields with their respective collection definitions
$multiValidator->addField('file1', new ImagesCollection());
$multiValidator->addField('multipleFileCollection', new DocumentsCollection());
$multiValidator->addField('profilePicture', new AvatarCollection());
// Validate data
$data = [
'file1' => $this->request->getFile('upload1'),
'multipleFileCollection' => $this->request->getFileMultiple('documents'),
'profilePicture' => $this->request->getFile('avatar')
];
if ($multiValidator->validate($data)) {
// Validation passed for all fields
// Process the files
} else {
// Validation failed
$errors = $multiValidator->getErrors();
// Handle errors
}
Working with ValidationRuleCollector
The ValidationRuleCollector
class is used internally by AssetConnectValidator
to collect validation rules from asset collection definitions. It implements the AssetCollectionSetterInterface
and provides methods to set various validation constraints.
How They Work Together
AssetConnectValidator
creates aValidationRuleCollector
for each field- The collection definition's
definition()
method is called with the rule collector - The rule collector collects validation rules based on the methods called on it
AssetConnectValidator
retrieves the collected rules and uses them for validation
ValidationRuleCollector Methods
The ValidationRuleCollector
provides the following methods for setting validation constraints:
File Validation
allowedExtensions(AssetExtension|string ...$extensions)
: Validates file extensionsallowedMimeTypes(AssetMimeType|string ...$mimeTypes)
: Validates MIME typessetMaxFileSize(float|int $maxFileSize)
: Validates maximum file sizesingleFileCollection()
: Ensures only a single file is uploadedonlyKeepLatest(int $maximumNumberOfItemsInCollection)
: Limits the number of files
Image Validation
setMaxImageDimensions(int $width, int $height)
: Validates maximum image dimensionssetMinImageDimensions(int $width, int $height)
: Validates minimum image dimensionsrequireImage()
: Ensures the file is an image
Advanced Usage
Validating Multiple File Uploads
For multiple file uploads, you can use the onlyKeepLatest
method to limit the number of files:
class MultipleImagesCollection implements AssetCollectionDefinitionInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
$definition
->allowedExtensions(AssetExtension::JPG, AssetExtension::PNG)
->allowedMimeTypes(AssetMimeType::IMAGE_JPEG, AssetMimeType::IMAGE_PNG)
->setMaxFileSize(2 * 1024 * 1024) // 2MB
->requireImage()
->onlyKeepLatest(5); // Allow up to 5 images
}
}
Then validate as usual:
$validator->setFieldCollectionDefinition('gallery_images', new MultipleImagesCollection());
if ($validator->validateFieldsFromRequest('gallery_images')) {
$images = $this->request->getFileMultiple('gallery_images');
// Process the images
}
Complete Example
Here's a complete example showing how to use AssetConnectValidator
with multiple fields and different collection definitions:
// Define collection definitions
class ProfileImageCollection implements AssetCollectionDefinitionInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
$definition
->allowedExtensions(AssetExtension::JPG, AssetExtension::PNG)
->allowedMimeTypes(AssetMimeType::IMAGE_JPEG, AssetMimeType::IMAGE_PNG)
->setMaxFileSize(1 * 1024 * 1024) // 1MB
->setMaxImageDimensions(500, 500)
->requireImage()
->singleFileCollection();
}
}
class DocumentsCollection implements AssetCollectionDefinitionInterface
{
public function definition(AssetCollectionSetterInterface $definition): void
{
$definition
->allowedExtensions(AssetExtension::PDF, AssetExtension::DOC, AssetExtension::DOCX)
->allowedMimeTypes(
AssetMimeType::APPLICATION_PDF,
AssetMimeType::APPLICATION_MSWORD,
AssetMimeType::APPLICATION_DOCX
)
->setMaxFileSize(5 * 1024 * 1024) // 5MB
->onlyKeepLatest(3); // Allow up to 3 documents
}
}
// In your controller
public function upload()
{
// Create a validator
$validator = new \Maniaba\AssetConnect\Validation\AssetConnectValidator();
// Set field collection definitions
$validator->setFieldCollectionDefinition('profile_image', new ProfileImageCollection());
$validator->setFieldCollectionDefinition('documents', new DocumentsCollection());
// Validate from request
if ($validator->validateRequest()) {
// Validation passed
// Get the files
$profileImage = $this->request->getFile('profile_image');
$documents = $this->request->getFileMultiple('documents');
// Process the files
// ...
return redirect()->to('/success')->with('message', 'Files uploaded successfully');
} else {
// Validation failed
$errors = $validator->getErrors();
return redirect()->back()->withInput()->with('errors', $errors);
}
}