Files
interview-demo-code/.cursor/rules/php.md
Nikita Kiselev 3cc82e45f0
Some checks are pending
Telegram Mini App Shop Builder / Compute version metadata (push) Waiting to run
Telegram Mini App Shop Builder / Run Frontend tests (push) Waiting to run
Telegram Mini App Shop Builder / Run Backend tests (push) Waiting to run
Telegram Mini App Shop Builder / Run PHP_CodeSniffer (push) Waiting to run
Telegram Mini App Shop Builder / Build module. (push) Blocked by required conditions
Telegram Mini App Shop Builder / release (push) Blocked by required conditions
Squashed commit message
2026-03-11 23:02:54 +03:00

244 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
<?php
declare(strict_types=1);
namespace App\Services;
```
### Array Syntax
```php
// ✅ Preferred short syntax
$array = ['key' => '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 {}
```