# Architectural Rules ## ECommerce Framework Architecture ### MVC-L Pattern The project uses a modified MVC-L pattern (Model-View-Controller-Language): - **Model**: Classes in `src/Models/` – data access and database operations - **View**: Vue components on the frontend, JSON responses on the backend - **Controller**: Handlers in `src/Handlers/` and `bastion/Handlers/` - **Language**: Translator in `framework/Translator/` ### Dependency Injection All dependencies are injected via the Container: ```php // ✅ Correct public function __construct( private Builder $builder, private TelegramCustomer $telegramCustomerModel ) {} // ❌ Incorrect public function __construct() { $this->builder = new Builder(...); } ``` ### Service Providers Services are registered via Service Providers: ```php class MyServiceProvider extends ServiceProvider { public function register(): void { $this->app->singleton(MyService::class, function ($app) { return new MyService($app->get(Dependency::class)); }); } } ``` ### Routes Routes are defined in `routes.php`: ```php return [ 'actionName' => [HandlerClass::class, 'methodName'], ]; ``` ### Handlers (Controllers) Handlers process HTTP requests: ```php class MyHandler { public function handle(Request $request): JsonResponse { // Validation // Business logic via Services // Return JsonResponse } } ``` ### Models Models work with data: ```php class MyModel { public function __construct( private ConnectionInterface $database, private Builder $builder ) {} public function findById(int $id): ?array { return $this->builder->newQuery() ->from($this->tableName) ->where('id', '=', $id) ->firstOrNull(); } } ``` ### Services Services contain business logic: ```php class MyService { public function __construct( private MyModel $model ) {} public function doSomething(array $data): array { // Business logic return $this->model->create($data); } } ``` ### Migrations Migrations live in `database/migrations/`: ```php return new class extends Migration { public function up(): void { $this->database->statement('CREATE TABLE ...'); } }; ``` ### Query Builder Always use Query Builder instead of raw SQL: ```php // ✅ Correct $query = $this->builder->newQuery() ->select(['id', 'name']) ->from('table_name') ->where('status', '=', 'active') ->get(); // ❌ Incorrect $result = $this->database->query("SELECT * FROM table_name WHERE status = 'active'"); ``` ### Frontend Architecture #### Admin Panel (Vue 3) - Composition API - Pinia for state management - PrimeVue for UI components - Axios for HTTP requests - Vue Router for navigation #### SPA (Telegram Mini App) - Composition API - Pinia stores - Tailwind CSS for styles - Telegram WebApp API - Vue Router ### Naming Conventions - **Classes**: PascalCase (`TelegramCustomerService`) - **Methods**: camelCase (`getCustomers`) - **Variables**: camelCase (`$customerData`) - **Constants**: UPPER_SNAKE_CASE (`MAX_RETRIES`) - **Files**: PascalCase for classes, kebab-case for everything else - **Tables**: snake_case with `acmeshop_` prefix ### Error Handling Always handle errors: ```php try { $result = $this->service->doSomething(); } catch (SpecificException $e) { $this->logger->error('Error message', ['exception' => $e]); throw new UserFriendlyException('User message'); } ``` ### Configuration Use configuration files in `configs/`: ```php $config = $this->app->getConfigValue('app.setting_name'); ``` ### Caching Use Cache Service for caching: ```php $cache = $this->app->get(CacheInterface::class); $value = $cache->get('key', function() { return expensiveOperation(); }); ```