Files
sides/.planning/codebase/CONVENTIONS.md

7.9 KiB

Coding Conventions

Analysis Date: 2026-05-20

Naming Conventions

Files:

  • Controllers: PascalCase (e.g., SirenController.php, AdminController.php, MapController.php)
    • Exception: cctvController.php uses lowercase — inconsistent with project convention
  • Models: PascalCase singular (e.g., User.php)
  • Exports: PascalCase (e.g., WaterLevelExport.php, HourlyRainfallExport.php)
  • Notifications: PascalCase (e.g., ResetPasswordNotification.php)
  • Services: PascalCase (e.g., FcmService.php)
  • Middleware: PascalCase (e.g., AdminMiddleware.php, LocalizationMiddleware.php)
  • Form Requests: PascalCase (e.g., ProfileUpdateRequest.php, LoginRequest.php)
  • Migrations: YYYY_MM_DD_HHMMSS_description_snake_case.php
  • Blade views: snake_case directories + kebab-case or snake_case files (e.g., layout/notification/rainfall.blade.php)
  • JavaScript: camelCase.js (e.g., homemap.js, graph.js, rfhistory.js)

Classes:

  • PascalCase for all classes, following PSR-4 autoloading
  • Controllers suffixed with Controller (e.g., RainfallController)
  • Exports suffixed with Export (e.g., HourlyRainfallExport)

Methods:

  • camelCase (e.g., stationDisplay(), rainfallSum(), exportHistoricalWl())
    • Exception: SirenHistory() uses PascalCase — inconsistent
  • Public methods in controllers follow action naming: index(), store(), update(), destroy(), edit()

Variables:

  • camelCase for local variables (e.g., $stationFilter, $rainfallData, $displayDate)
  • camelCase for class properties (e.g., $stationid, $startDate in Export classes)
  • $stationid used as one word (not $stationId) — project-specific convention

Database Tables:

  • snake_case lowercase singular (e.g., station, rainfall, waterlevel, siren, notification, users)
  • users is the only plural table name

Columns:

  • snake_case lowercase (e.g., stationid, active_time, access_level, login_attempts, is_blocked, cctv_link)
  • No consistent convention: some use compound words without underscore (e.g., stationid, waterlevel)

Code Style

Formatting:

  • .editorconfig present at both project root and src/
  • Indent: 4 spaces (no tabs, except Makefiles)
  • Charset: UTF-8
  • End of line: LF
  • Trailing whitespace trimmed (except .md files)
  • YAML files: 2-space indent
  • No ESLint or Prettier configured for JavaScript

Linting:

  • laravel/pint installed as dev dependency (PHP code style fixer)
  • No evidence of a pint.json configuration file — using defaults
  • No frontend linting tools configured

Bracket Style:

  • Opening braces on same line for classes and methods
  • Control structures: opening brace on same line (K&R style)
  • Multi-line function calls and arrays: trailing comma not consistently used

Import/Use Statement Organization:

  • Laravel framework imports first
  • Then third-party packages (e.g., Carbon, Maatwebsite\Excel, DomPDF)
  • Then application imports (e.g., App\Models\User, App\Services\FcmService)
  • Blank line between groups is not consistently applied
  • Example from WaterLevelController.php:
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\DB;
    use Carbon\Carbon;
    // Add this for Export data to excel
    use App\Exports\WaterLevelExport;
    use Maatwebsite\Excel\Facades\Excel;
    

Docblock Usage:

  • PHPDoc blocks present on model properties ($fillable, $hidden, casts())
  • Docblocks on factory methods and notification methods (Breeze scaffolded)
  • Custom controllers use inline // comments extensively rather than docblocks
  • Comment style in controllers follows a pattern:
    // Function Retrieve Current Water Level Data
    public function index(Request $request)
    
  • Each SQL query is annotated with block comments:
    // TABLE : STATION JOIN TABLE WATERLEVEL
    // COLUMN : name,datetime,waterlevel
    // INPUT :  $stationCondition from resources/views/...
    // OUTPUT : resources/views/layout/waterlevel.blade.php
    

File Organization

How files are grouped:

  • Controllers grouped by domain in flat structure under app/Http/Controllers/
  • API controllers in app/Http/Controllers/Api/ subdirectory
  • Auth controllers in app/Http/Controllers/Auth/ subdirectory (Breeze scaffolded)
  • Exports in app/Exports/
  • Services in app/Services/
  • Notifications in app/Notifications/
  • Views follow a layout.{domain} naming pattern (e.g., layout.rainfall, layout.admin.stationmgmt)

One class per file:

  • Adhered to throughout — one class per file

Directory naming:

  • All lowercase directories (e.g., Controllers/, Models/, Services/, Exports/)
  • Views use nested lowercase directories (e.g., layout/notification/history/)

Git Conventions

Branch naming:

  • Only 2 commits in the repository — no discernible branch naming convention

Commit message patterns:

  • Observed messages:
    • first commit
    • fix: configuration docker-compose.yml
  • The second commit suggests a possible type: description convention (fix:, feat:, etc.)

Laravel-Specific Patterns

Eloquent Model Patterns:

  • Only User.php exists as an Eloquent model (app/Models/User.php)
  • HasFactory and Notifiable traits used on User
  • $fillable array for mass assignment (not $guarded)
  • casts() method (Laravel 12 style) instead of $casts property
  • Custom notification override: sendPasswordResetNotification()

Controller Patterns:

  • Not resource controllers — methods are custom-named (e.g., stationDisplay(), userDisplay(), storeStation())
  • Heavy use of raw SQL via DB::select() and DB::table() instead of Eloquent ORM
  • collect(DB::select(...)) pattern to wrap raw SQL results into collections
  • Controller validation done inline with $request->validate() — not consistently using Form Requests
  • Redirect pattern: redirect()->back()->with('success', __('toast.key'))
  • View compact pattern: return view('blade.path', compact('var1', 'var2'))

Form Request Usage:

  • ProfileUpdateRequest for profile updates (app/Http/Requests/ProfileUpdateRequest.php)
  • LoginRequest for authentication (app/Http/Requests/Auth/LoginRequest.php)
  • Admin controller does inline $request->validate() instead of Form Requests
  • Inconsistent: Form Requests exist but most validation is inline

Resource/API Resource Usage:

  • Not used — API responses use response()->json($data) directly
  • No API Resource classes defined

Policy Usage:

  • Not used — authorization handled via custom AdminMiddleware checking access_level
  • app/Http/Middleware/AdminMiddleware.php checks Auth::user()->access_level !== 1

Event/Listener Patterns:

  • Not used — no events or listeners defined
  • Notification push (FCM) is called directly from API controller

Route Patterns:

  • Named routes used consistently: ->name('rainfall'), ->name('stationmanagement.store')
  • Route grouping by middleware: Route::middleware('auth'), Route::middleware(['admin'])
  • Admin routes use POST for updates (not PUT/PATCH) — non-RESTful
  • API routes in routes/api.php with no auth middleware

Localization:

  • Bilingual: English (en) and Bahasa Malaysia (bm) in resources/lang/
  • LocalizationMiddleware sets locale via session
  • __('key') helper used for translations in views and controllers

Middleware:

  • Custom middleware registered in bootstrap/app.php
  • AdminMiddleware for admin-only routes
  • LocalizationMiddleware for language switching

Export Pattern (Maatwebsite Excel):

  • Export classes implement FromCollection, WithHeadings, ShouldAutoSize
  • Constructor injection for filter parameters
  • Raw SQL queries in collection() method
  • headings() method returns array of column names

PDF Export Pattern (DomPDF):

  • Pdf::loadView('blade.path', compact('data'))->setPaper('a4','potrait')
  • Note: 'potrait' is a typo — should be 'portrait' (present in multiple files)

Convention analysis: 2026-05-20