Created Classes And Files
Models
As mentioned before you'll find a model class corresponding to the name you entered
- the model will have the needed methods to represent your relations
- if you have a property of type
boolyou'll see a scope for it to make it easier to query data based on this property - you'll notice the existence of
searchableArray()method in the returned array of this method you can define the searchable columns in the table of this model so in the index method if you passed a query param namedsearchwith the value of the wanted value the index method will search within the defined columns in thesearchableArray()method . - you'll notice the existence of
relationsSearchableArray()method in the returned array of this method you can define the related tables and their desired columns to search within in the same way for thesearchableArray()method . - file columns are handled through the
MediaCastcast together with theHasMediatrait (both added to the model automatically). Any column cast to\App\Casts\MediaCast::classis treated as a file: when you create or update a record the uploaded file is stored and its path is saved in that column, and the file is cleaned up when the record is deleted. You don't need to maintain a list of file columns by hand.
you'll find that we have already filled those arrays with appropriate values, but you can change them according to your preferences
an extended explanation here
Migrations
the corresponding created migration will match the types of the columns you entered before
NOTE
columns of type files will be placed on the migration file as a string columns with a nullable attribute
NOTE
columns of type key will be placed on the migration file as a foreignIdFor columns with these attributes :
- constrained
- cascadeOnDelete
NOTE
columns of type translatable will be placed on the migration file as a json columns
TIP
it is always better to check on the created files
Controllers
the created controller contains the five basic methods (index , show , store , update , destroy) in addition to excel files exporting and importing methods (export , import , getImportExample)
Requests
each model property will have this rules : required|PropertyType unless this :
| property name | rules |
|---|---|
| name,first_name ,last_name | required,string ,min:3 ,max:255 |
| required,string,max:255 ,email | |
| password | required,string,max:255 ,min:6 ,confirmed |
| phone , phone_number , number | required,string,max:255 ,min:6 |
any word ends with _at (started_at , ends_at , … , any type that seems to be a date type) | required,date |
any word starts with is_ (is_original , is_available , …. , any type that seems to be boolean value) | required,boolean |
any word ends with _id (user_id , product_id , …. , any type that seems to be foreign key) | required,integer,exists:parent table,id |
| columns with file type | nullable,image,mimes:jpeg,png,jpg,max:2048 |
| columns with text type | nullable ,string |
| columns with translatable type | required , json , new ValidTranslatableJson |
CAUTION
it is important to check on the rules of the created form request after each created model to make sure that these rules are compatible with your application purposes and to check if there is any invalid rule usage
DTOs
When you pick DTO or Both as the validation type while installing (php artisan cubeta:install api|web|react-ts, or the GUI settings page), each model also gets a App\DTOs\<version>\<Model>\StoreUpdate<Model>DTO class extending WendellAdriel\ValidatedDTO\ValidatedDTO from the wendelladriel/laravel-validated-dto package (installed for you).
The DTO carries the same rules the form request gets, plus typed properties and casts inferred from the column types (IntegerCast, FloatCast, BooleanCast, StringCast). It is injected directly into the generated controllers, which read the validated data with $dto->toArray():
public function store(StoreUpdateProductDTO $dto)
{
$item = $this->productService->store($dto->toArray(), $this->relations);
// ...
}NOTE
When the validation type is Both, both classes are generated but the generated controllers depend on the form request.
Resources
Fore each created model there will be a corresponding Json Resource class which extends the BaseResource class , this class extends the functionality of the JsonResource class and allows you to extend it more BaseResource class is explained here.
WARNING
this resource will return the relations of this model also
Factories
the created factory fill the database according to this :
| Model Property Type | Faker Line |
|---|---|
| integer|bigInteger|unsignedBigInteger | fake()->numberBetween(1,2000) |
| key type columns | a factory for the related model |
| translatable type column | json_encode(["en":fake()->word()]) in fact the array inside the json_encode method will be a fake word for each available locale you defined in the cubeta-starter.php config file |
| double | fake()->randomFloat(1,2000) |
| float | fake()->randomFloat(1,2000) |
| string | fake()->sentence() |
| text | fake()->text() |
| json |
if the property is not in those types then this will be applied according to its name:
| Property Name | The Applied Faker |
|---|---|
any word ends with _at (started_at , ends_at , ... , any type that seems to be a date type) | fake()->date() |
any word starts with _is (is_original , is_available , .... , any type that seems to be boolean value) | fake()->boolean() |
any word ends with _id (user_id , product_id , .... , any type that seems to be foreign key) | \App\Models\ Related Model Class::factory() |
- sometimes the factory could be predicted according to its name like if you have a column named image , logo , icon the used faker will be
imageUrl()or if the name of the column contain the phone word the used faker will bephoneNumber().
if the model has one of this relation (has many , many to many) a function like below will be added to the factory :
public function withProducts($count = 1)
{
return $this->has(\App\Models\Product::factory($count));
};Seeders
the seeder will call the corresponding factory of the model with 10 as the factory count parameter
Repositories
if you're not familiar with the repository design pattern I'll give you a brief :
The main idea behind the Repository pattern is to create an abstraction layer between the application and the data source. This abstraction layer is called the repository. The repository acts as a mediator between the application and the data store. It encapsulates the logic required to access the data and provides a simple and consistent interface for the application to interact with the data.
may you want to read more, so we recommend this article : introduction to repository design pattern
and based on that we placed the code that handle the database operations and queries on the repository layer and this layer will be placed above the model layer and before the service layer (we will talk about it later) .
so any database operation related to your model we prefer you do it in the corresponding repository class .
each repository is a singleton — you obtain it via its static make() method (provided by the Makable trait) rather than through dependency injection.
if you opened the created repository class you'll notice that it extends another class named BaseRepository, and it is in the app/Repositories/Contracts Directory check on it here.
Services
if you're not familiar with the service design pattern I'll give you a brief :
The Service Design Pattern consists of two main components: the service layer and the service interface. The service layer is responsible for implementing the business logic and data access of the application. It typically contains classes and methods that perform specific tasks, such as retrieving data from a database, performing calculations, or sending emails. The service layer should be designed to be reusable and easy to test.
may you want to read more, so we recommend this article : Service Design Patterns
and based on that we placed the code that handle the logic on the service layer and this layer will be placed above the repository layer .
after your model creation is done you'll find a YourModelService.php file in the services directory you defined in the package config file.
if you opened the service class you'll notice that it extends BaseService and uses the Makable trait, so — like repositories — you obtain it through its static make() method rather than dependency injection. It also declares a $repositoryClass property pointing at the model's repository, which the base service uses for all data access.
Tests
foreach created model there will be a corresponding test class which extends MainTestCase you can find it in the tests/Feature directory , this test class will test the CRUD endpoints , in the created test you'll see the following variables : $model , $resource , $userType , $baseUrl and you'll see that there is two of them have a value , but if we go to the others you need to know the following:
$userType: if your application use multi actors by this package so in this variable just give it the actor role for those endpoints if there is not just leave it as'none'.$baseUrl: if you've checked on the appended rout of your model you'll notice that this route is named so here you just put the name of it like if the route name is 'brands' just put the value of it as 'brands'.
maybe you want to check on MainTestCase class trait to know how the test methods work and see if they are good for you, or you have to create another ones .
Postman Collection
the generated postman collection will have HTTP requests grouped by your model name . it has two variables for the whole collection :
- : this will be generated as we mentioned before from the value you defined in the config.
- : this will represent the accept-language header in all the generated requests
when generating another postman collection assuming that you've already generated one it will not replace the older one it will just add a new group of requests to the previous one .
