Programming rules - JoseTor101/ApollosGearShop GitHub Wiki

General recommendations

  • Use Comments in English: All comments and documentation must be written in English for consistency.
  • Parameter Type-Hinting and return type: Always type-hint parameters for better clarity and validation and return type for functions:
function calculateTotalPrice(float $price, float $taxRate): float
{
   //your code
}
  • Getter and Setter Usage: Instead of directly accessing object properties, use getters and setters to maintain encapsulation.
<h1>{{ $review->getTitle() }}</h1>
<p>{{ $review->getDescription() }}</p>
  • Use Key-Value Format: When working with arrays, always use the key-value format to improve clarity and prevent errors.
$viewData = [
    'title' => __('Title'),
    'subtitle' => __('Subtitle'),
    'reviews' => $reviews,
];

1. Models

  • Comment model attributes and relationships: Use the following sintax to describre the current model you are working on:
/*
     * ORDER ATTRIBUTES

     * $this->attributes['id'] - int - contains the order primary key (id)
     * $this->attributes['user_id'] - int - contains the user id of the order
     * $this->attributes['creationDate'] - date - contains the creation date of the order
     * $this->attributes['deliveryDate'] - date - contains the delivery date of the order
     * $this->attributes['totalPrice'] - int - contains the order total price
     *
     * RELATIONSHIPS
     *
     * User - belongsTo
     * ItemInOrder - hasMany
*/
  • Getters and Setters: Access model attributes using getters and setters for encapsulation and maintainability.
  • Keep Models Clean: Models should only contain the properties and methods that relate to the database table they represent. Avoid placing business logic or heavy processing in models.
  • Validation in Models: As a best practice, validate input data in models, ensuring that controllers only delegate tasks. For example:
public function validate(array $data): array
{
    $validator = Validator::make($data, [
        'description' => 'required|max:255',
        'score' => 'required|integer|min:1|max:5',
    ]);

    return $validator->validated();
}
  • Use Eloquent Relationships: Leverage Eloquent's built-in relationship methods (e.g., hasOne, belongsTo, hasMany) to define relationships between models.
  • Mass Assignment Protection: Use $fillable or $guarded properties to protect against mass assignment vulnerabilities.
  • Scope Queries: Utilize query scopes for reusable query logic, making your queries more readable and reusable across the application.
  • Factories: Each model must have a factory file. Create one using:
php artisan make:factory <modelName>Factory

2. Views

  • Folder management: Each model if intended to use in frontend, must have a separated folder for its views. Those folders must be named after the model.
  • Blade Templates Only: All views must be created using Blade templating engine. Do not mix PHP directly within Blade templates; use Blade's syntax instead.
  • Use layouts: Reusable code as headers and footer must go inside a layout, located at resources/views/layouts
  • Avoid Logic in Views: Business logic should not be present in views. Keep views focused on presentation, using Blade's control structures (@if, @foreach) sparingly and appropriately.
  • Pass Data from Controllers: Data used in views should be passed from controllers or view composers, not hardcoded into the view files.
  • Access information from model with its corresponding getters and setters.
  • Getter and Setter Usage: Instead of directly accessing object properties, use getters and setters to maintain encapsulation.
<h1>{{ $review->getTitle() }}</h1>
<p>{{ $review->getDescription() }}</p>

3. Controllers

  • Pass data to views using viewData array: use the key-value in viewData array to pass data from controller to view.
$viewData = [
    'title' => __('Title'),
    'subtitle' => __('Subtitle'),
    'reviews' => $reviews,
];

return view('review.index')->with('viewData', $viewData);
  • Follow RESTful Conventions: Adhere to RESTful principles by naming your controller methods appropriately (index, show, store, update, destroy).
  • Avoid Business Logic in Controllers: Controllers should delegate business logic to service classes, utils or models, keeping the controllers thin and focused on handling HTTP requests.
  • Parameter Type-Hinting and return type: Always type-hint parameters for better clarity and validation and return type for functions:
function calculateTotalPrice(float $price, float $taxRate): float
{
   //your code
}

4. Routes

  • RESTful Routes: Define routes following RESTful conventions, keeping route definitions concise and meaningful.
  • Named Routes: Always use named routes for easier referencing and maintenance within views and controllers.
  • Route to Controllers: Every route must be associated with a controller method. Avoid using closures in route definitions, as they are harder to test and maintain.
  • Access controller sintax: We prefer static names, example: Example:
Route::get('/instruments', 'App\Http\Controllers\InstrumentController@index')->name('instrument.index');
  • Security groups: Instead of verifying authentication in each route, create checkgroups with middlewares in the web.php file to handle the per
Route::middleware([CheckGroup::class . ':user'])->group(function () {
}
Route::middleware([CheckGroup::class.':admin'])->group(function () {
}

5. Migrations

  • Model creation: On model creation add a new migration file, such file must contain model's attributes and relationships. Remember, to create a new migration run
php artisan make:migration migration_name

Model migration example:

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        if (!Schema::hasTable('instruments')) {
            Schema::create('instruments', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->string('description');
                $table->string('category');
                $table->string('brand');
                $table->integer('price');
                $table->float('reviewSum')->default(0); 
                $table->integer('numberOfReviews')->default(0);
                $table->integer('quantity')->default(1);
                $table->string('image');
                $table->timestamps();

            });
        }
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('instruments');
    }
};
  • Model changes: Each change in model attributes must be accompanied with a migration file, with a sintax as shown below:
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::table('users', function (Blueprint $table) {
            if (! Schema::hasColumn('users', 'role')) {
                $table->string('role')->default('user');
            }
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('role');
            //
        });
    }
};

Additional Suggestions

  • Lang Tags: Use language tags for translatable strings in the views. This ensures better maintainability and localization support.
<h1>{{ __('review.create_title') }}</h1>
⚠️ **GitHub.com Fallback** ⚠️