This is a laravel package that will help you easily create data transfer objects from requests and arrays by simple using four simple steps:
- Install package
- Create DTO through commandline
- Set public properties of the class
- Then create your DTOs from requests or arrays
The DTO sets the properties with values from request or array so that this property bag (data transfer object) can be passed on to your functions in parts of your controllers, services or even actions;
Install package using composer
composer require mr-robertamoah/dto
To start configuring the workings of this package, first publish the configuration file using:
php artisan vendor publish --tag=dto-config
This command adds dto.php
file in the config folder.
The following shows the keys of the config file and what they do:
- folderName: This will help you use a folder name other than DTOs which is the default
- attachDTO: If this is set to
true
the name of every DTO you create will end with DTO - forcePropertiesOnDTO: An exception is thrown whenever you try to set a value to a non-existent property. Setting this to
true
will dynamically create the property on the DTO object. - suppressPropertyNotFoundException: When set to
true
, no DTOPropertyNotFoundException will be thrown, rather, the object will be returned. - suppressMethodNotFoundException: When set to
true
, no DTOMeothdNotFoundException will be thrown, rather, the object will be returned.
Below are a break down of how to use the DTO
You can always create a file manually and extend the BaseDTO
class or use laravel's artisan commands.
php artisan dto:make UserDTO
Note the following options on the command:
--folderName
: point to the app folder in which to create the DTO--attachDTO
: whether or not to attach DTO to the name of the files and classes--force
: force the creation of a file even if file already exists You can create multiple files as well.
php artisan dto:make UserDTO ImageDTO
class UserDTO extends BaseDTO
{
public $name;
public $email;
}
public function create(Illuminate\Http\Request $request)
{
$dto = UserDTO::fromRequest($request);
//or
$dto = UserDTO::new()->fromRequest($request);
}
Note that this request should be of type Illuminate\Http\Request
.
public function create(Illuminate\Http\Request $request)
{
$data = [
'name' => 'Robert Amoah',
'email' => 'mr_robertamoah@yahoo.com',
];
$dto = UserDTO::fromArray($data);
//or
$dto = UserDTO::new()->fromArray($data);
}
public function create(Illuminate\Http\Request $request)
{
$dto = UserDTO::fromRequest($request);
$user = UserService::createUser($dto);
}
public function createUser(UserDTO $userDTO)
{
$user = User::create($userDTO->getFilledData());
}
You can extend either fromArray
or fromRequest
methods using fromArrayExtension
and fromRequestExtension
protected methods respectively. These methods will receive the first arguments (the array and request respectively) passed into the main creation methods and must return the same object;
class UserDTO extends BaseDTO
{
public $name;
public $email;
public $date;
protected function fromRequestExtenstion(Illuminate\Http\Request $request) : BaseDTO
{
return $this->date = new Carbon();
}
protected function fromArrayExtenstion(array $data) : BaseDTO
{
return $this->date = new Carbon();
}
}
This section shows you the protected properties available on the BaseDTO
class which helps you get the best out of your dto objects.
If you would want to get some properties other than the filled ones then you have to indicate the properties in this array
// dto class
class UserDTO extends BaseDTO
{
protected array $dtoDataKeys = [
'name', 'email'
];
}
//in services, controller or actions
public function createUser(UserDTO $userDTO)
{
$user = User::create($userDTO->getData());
}
Note that the getData
method will return an empty array if no property is added to the dtoDataKeys
. If you pass true
to the method like getData(true)
, then properties that have been filled will be returned as an array.
This property helps you set the appropriate property names for files to be retrieved from a request as well as easily get an array of all such properties by using the getFiles
method.
// dto class
class UserDTO extends BaseDTO
{
protected array $dtoFileKeys = [
'image1', 'image2'
];
}
// in service
public function createUser(UserDTO $userDTO)
{
foreach($userDTO->getFiles() as $key => $file) {
$file->save();
}
}
Also, dtoDataKeys
and dtoFileKeys
can both be set dynamically by calling the setDataKeys
and setFileKeys
methods respectively on an object. The append versions of these methods adds extra keys to the arrays (dtoDataKeys and dtoFileKeys).
UserDTO::new()
->setDataKeys(['name', 'email'])
->setFileKeys('image1, image2');
Add the names of properties to this array if you do not want it to given a value during the creation of a DTO.
// dto class
class UserDTO extends BaseDTO
{
protected array $dtoExclude = [
'image1',
];
}
Add the names of properties to this array if you only want them to be given a value during the creation of a DTO. In the example below, only name and emails will be given a value during the creation of the DTO.
// dto class
class UserDTO extends BaseDTO
{
public $name;
public $email;
public $age;
protected array $dtoExclude = [
'name', 'email'
];
}
Note that the dtoOnly
will take precendence over the dtoExclude
once it has at least one entry.
These methods allow you to use the dto fluently while getting the most out of it.
This allows you to call a public method which starts with with
and ends with the name of a property. The argument of this method should be the value you wish to assign to the property. The method will return the DTO after the value has be assigned.
// in service
public function createUser(UserDTO $userDTO)
{
$userDTO = $userDTO->withName('James Coffie');
$user = User::create($userDTO->getData()):
}
This allows you to pass an array that contains property names as keys that point to values you would want assigned to the DTO. The keys of the array must match the names of the properties to which you want values assigned. The method will return the DTO after the value has be assigned.
// in service
public function createUser(UserDTO $userDTO)
{
$userDTO = $userDTO->addData([
'name' => 'James Coffie',
'email' => 'jamescoffie123@zigzag.org',
]);
$user = User::create($userDTO->getData()):
}
This is a static method that allows you to create an new object from the DTO class.
// in controller
public function create($request)
{
$userDTO = UserDTO::new();
$user = UserService::create(
$userDTO->setFileKeys(['image1', 'image2'])->fromRequest($request)
):
}
The DTO will throw a DTOPropertyNotFound exception when you try to assign a value to a property not set in the DTO class. A property will be set dynamically when you use this method before creating the DTO.
// in controller
public function create($request)
{
$userDTO = UserDTO::new();
$user = UserService::create(
$userDTO->forceProperties()->fromRequest($request)
):
}
These are the following exceptions that are thrown by this package:
- DTOPropertyNotFound
- DTOMethodNotFound
- DTOWrongArgument
- DTOFileAlreadyExists
Note that DTOFileAlreadyExists can only thrown in console whereas the others can only be thrown when using the DTO. You can suppress DTOPropertyNotFound
and DTOMethodNotFound
exceptions in the configuration file.