Skip to content

Development Guide

Prerequisites

  • PHP 8.1
  • Composer
  • Node.js + npm
  • MySQL
  • Redis
  • Octane-compatible server (Swoole or RoadRunner)

Local Setup

composer install
npm install
cp .env.example .env
php artisan key:generate
php artisan migrate
php artisan db:seed

Required .env values

# App
APP_URL=
APP_KEY=

# Database
DB_CONNECTION=mysql
DB_HOST=
DB_PORT=3306
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=

# Redis
REDIS_HOST=
REDIS_PASSWORD=

# Session
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis

# Payment: SBPS (account IDs + keys for service and goods payment types)
SBPS_SERVICE_ACCOUNT_ID=
SBPS_SERVICE_SERVICE_KEY=
SBPS_SERVICE_SERVICE_SECRET=
SBPS_SERVICE_CONTINUOUS_SECRET=
SBPS_GOODS_ACCOUNT_ID=
SBPS_GOODS_SERVICE_KEY=
SBPS_GOODS_SERVICE_SECRET=
SBPS_PRODUCTION_URL=
SBPS_STAGING_URL=
SBPS_DEVELOPMENT_URL=
SBPS_PRODUCTION_URL_MODIFY=
SBPS_STAGING_URL_MODIFY=
SBPS_DEVELOPMENT_URL_MODIFY=

# Payment: Atone (production + test key pairs)
ATONE_API_KEY=
ATONE_API_SECRET=
ATONE_TEST_API_KEY=
ATONE_TEST_API_SECRET=
ATONE_API_ENDPOINT=
ATONE_TEST_API_ENDPOINT=
ATONE_SCRIPT_URL=
ATONE_TEST_SCRIPT_URL=

# Google Maps
GOOGLE_MAPS_API_KEY=

# Mail
MAIL_MAILER=
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=

# Chekicha (CKC platform)
CKC_SERVICE_DOMAIN=
CKC_TOKEN_HASH=

# JWT (guest cart identity)
JWT_SECRET=

# reCAPTCHA (registration, inquiry)
RECAPTCHA_SITE_KEY=
RECAPTCHA_SECRET_KEY=

# Storage: S3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
AWS_BUCKET=

# Sentry
SENTRY_LARAVEL_DSN=

Running the Application

# Development (frontend hot reload + Laravel server)
composer run dev
# or separately:
npm run dev
php artisan serve

# Production-like with Octane
php artisan octane:start

# Queue worker (required for notifications)
php artisan queue:work

# Scheduler (required for product publish, lottery, reporting)
php artisan schedule:run  # or: php artisan schedule:work

Frontend Build

npm run dev    # hot module reload
npm run build  # production build

If you see a ViteException: Unable to locate file in Vite manifest error, run npm run build or npm run dev.

The frontend uses: - Vue 3 + <script setup> SFCs - Inertia.js v0 (@inertiajs/vue3) - Ziggy for named routes in JS (import { route } from 'ziggy-js') - Vite for bundling

Making Code Changes

Creating a new module action

php artisan make:class app/Modules/{Module}/Actions/{ActionName}Action

Pattern: receive a DTO, perform a single operation, return result or throw.

Creating a Form Request

php artisan make:request Web/{Domain}/{RequestName}Request

Check sibling requests in app/Http/Requests/ for whether the project uses array or string validation rules.

Database migrations

php artisan make:migration create_{table}_table
php artisan migrate

Data-only migrations go in database/migrations/data_migration/ (separate from schema migrations).

Running tests

php artisan test                                 # all tests
php artisan test tests/Feature/SomeTest.php      # specific file
php artisan test --filter=testMethodName         # specific test

Current state: Only placeholder test scaffold exists. No real tests. See Architecture — Risk Signals for priority areas.

Linting / Formatting

vendor/bin/pint --dirty    # fix formatting on changed files
vendor/bin/pint            # fix all

Run Pint before committing.

Key Artisan Commands

php artisan queue:work                # process jobs/notifications
php artisan schedule:work             # run scheduler loop (dev)
php artisan octane:start              # start Octane server
php artisan octane:reload             # reload workers after code change (prod)
php artisan route:list                # list all routes
php artisan tinker                    # REPL for Eloquent queries

Module Structure

Each module in app/Modules/{Name}/ follows this structure:

Actions/       — single-responsibility CQRS operations
DTOs/          — spatie/laravel-data typed input objects
Events/        — domain events
Filters/       — timedoor/laravel-filter query filters
Interfaces/    — contracts (bound in Providers/)
Jobs/          — queued or scheduled jobs
Listeners/     — event listeners
Notifications/ — email/notification classes
Policies/      — authorization policies
Providers/     — service provider + IoC bindings
QueryBuilders/ — custom Eloquent query builder extensions

Not all modules have all directories.

Git Workflow

Current branch: staging. Main branch: master.

Active development area: Lottery module (multiple recent PRs). SendLotteryWinnerEmailJob has uncommitted changes on staging — check before merging.