# PHP Code Style Rules ## PHP Version The project supports PHP 7.4+ ## PSR Standards - **PSR-1**: Basic Coding Standard - **PSR-4**: Autoloading Standard - **PSR-12**: Extended Coding Style ## Code Style ### Type Declarations ```php // ✅ Correct – strict typing public function getCustomers(Request $request): JsonResponse { $id = (int) $request->get('id'); return new JsonResponse(['data' => $customers]); } // ❌ Incorrect – no types public function getCustomers($request) { return ['data' => $customers]; } ``` ### Nullable Types ```php // ✅ Correct public function findById(?int $id): ?array { if ($id === null) { return null; } return $this->query->where('id', '=', $id)->firstOrNull(); } ``` ### Strict Types Always use `declare(strict_types=1);`: ```php 'value']; // ❌ Do not use $array = array('key' => 'value'); ``` ### String Interpolation ```php // ✅ Preferred $message = "User {$userId} not found"; // ✅ Alternative $message = sprintf('User %d not found', $userId); ``` ### Arrow Functions (PHP 7.4+) ```php // ✅ For simple operations $filtered = array_filter($items, fn($item) => $item->isActive()); // ❌ For complex logic – use regular functions ``` ### Nullsafe Operator (PHP 8.0+) ```php // ✅ For PHP 7.4 $name = $user && $user->profile ? $user->profile->name : null; ``` ## Naming Conventions ### Classes ```php // ✅ PascalCase class TelegramCustomerService {} class UserRepository {} ``` ### Methods ```php // ✅ camelCase public function getCustomers(): array {} public function saveOrUpdate(array $data): array {} ``` ### Variables ```php // ✅ camelCase $customerData = []; $totalRecords = 0; ``` ### Constants ```php // ✅ UPPER_SNAKE_CASE private const MAX_RETRIES = 3; public const DEFAULT_PAGE_SIZE = 20; ``` ### Private Properties ```php // ✅ camelCase with visibility modifier private string $tableName; private Builder $builder; ``` ## Documentation ### PHPDoc ```php /** * @throws ValidationException If parameters are invalid */ public function getCustomers(Request $request): JsonResponse { // ... } ``` ### Inline Comments ```php // ✅ Useful comments // Apply filters to calculate total number of records $countQuery = $this->buildCountQuery($filters); // ❌ Obvious comments // Get data $data = $this->getData(); ``` ## Error Handling ### Exceptions ```php // ✅ Specific exceptions if (!$userId) { throw new InvalidArgumentException('User ID is required'); } // ✅ Logging try { $result = $this->service->process(); } catch (Exception $e) { $this->logger->error('Processing failed', [ 'exception' => $e, 'context' => $context, ]); throw new ProcessingException('Failed to process', 0, $e); } ``` ## Query Builder Usage ### Always Use Query Builder ```php // ✅ Correct $customers = $this->builder->newQuery() ->select(['id', 'name', 'email']) ->from('acmeshop_customers') ->where('status', '=', 'active') ->orderBy('created_at', 'DESC') ->get(); // In edge cases raw SQL may be used $result = $this->database->query("SELECT * FROM acmeshop_customers"); ``` ### Parameter Binding ```php // ✅ Query Builder automatically binds parameters $query->where('name', 'LIKE', "%{$search}%"); // ❌ Never concatenate values into SQL, avoid SQL Injection. ``` ## Array Access ### Safe Array Access ```php // ✅ Use Arr::get() use Acme\ECommerceFramework\Support\Arr; $value = Arr::get($data, 'key', 'default'); // ❌ Unsafe $value = $data['key']; // may trigger an error ``` ## Return Types ```php // ✅ Always specify return type public function getData(): array {} public function findById(int $id): ?array {} public function process(): void {} // ❌ Without type public function getData() {} ``` ## Visibility Modifiers ```php // ✅ Always specify visibility modifier private string $tableName; protected Builder $builder; public function getData(): array {} ```