Skip to content

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 bool you'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 named search with the value of the wanted value the index method will search within the defined columns in the searchableArray() 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 the searchableArray() method .
  • file columns are handled through the MediaCast cast together with the HasMedia trait (both added to the model automatically). Any column cast to \App\Casts\MediaCast::class is 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 :

  1. constrained
  2. 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 namerules
name,first_name ,last_namerequired,string ,min:3 ,max:255
emailrequired,string,max:255 ,email
passwordrequired,string,max:255 ,min:6 ,confirmed
phone , phone_number , numberrequired,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 typenullable,image,mimes:jpeg,png,jpg,max:2048
columns with text typenullable ,string
columns with translatable typerequired , 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():

php
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 TypeFaker Line
integer|bigInteger|unsignedBigIntegerfake()->numberBetween(1,2000)
key type columnsa factory for the related model
translatable type columnjson_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
doublefake()->randomFloat(1,2000)
floatfake()->randomFloat(1,2000)
stringfake()->sentence()
textfake()->text()
json

if the property is not in those types then this will be applied according to its name:

Property NameThe 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 be phoneNumber().

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:

  1. $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'.
  2. $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 :

  1. : this will be generated as we mentioned before from the value you defined in the config.
  2. : 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 .

Released under the MIT License.