module Geliştirmede En İyi Uygulamalar
Genel Bakış
Section titled “Genel Bakış”Bu belge, yüksek kaliteli XOOPS modülleri geliştirmeye yönelik en iyi uygulamaları birleştirir. Bu yönergelere uyulması, modüllerin bakımı kolay, güvenli ve performanslı olmasını sağlar.
Mimarlık
Section titled “Mimarlık”Temiz Mimariyi Takip Edin
Section titled “Temiz Mimariyi Takip Edin”Kodu katmanlar halinde düzenleyin:
src/├── Domain/ # Business logic, entities├── Application/ # Use cases, services├── Infrastructure/ # Database, external services└── Presentation/ # Controllers, templatesTek Sorumluluk
Section titled “Tek Sorumluluk”Her sınıfın değişmek için bir nedeni olmalıdır:
// Good: Focused classesclass ArticleRepository { /* persistence only */ }class ArticleValidator { /* validation only */ }class ArticleNotifier { /* notifications only */ }
// Bad: God classclass Article { public function save() { } public function validate() { } public function notify() { } public function generatePDF() { }}Bağımlılık Enjeksiyonu
Section titled “Bağımlılık Enjeksiyonu”Bağımlılıkları enjekte edin, oluşturmayın:
// Goodpublic function __construct( private readonly ArticleRepositoryInterface $repository) {}
// Badpublic function __construct() { $this->repository = new ArticleRepository();}Kod Kalitesi
Section titled “Kod Kalitesi”Tip Güvenlik
Section titled “Tip Güvenlik”Katı türleri ve tür bildirimlerini kullanın:
<?php
declare(strict_types=1);
final class ArticleService{ public function findById(int $id): ?Article { // ... }
public function create(CreateArticleDTO $dto): Article { // ... }}Hata İşleme
Section titled “Hata İşleme”İstisnaları uygun şekilde kullanın:
// Throw specific exceptionsthrow new ArticleNotFoundException($id);throw new ValidationException($errors);throw new UnauthorizedException('Cannot edit this article');
// Catch at appropriate leveltry { $article = $service->create($dto);} catch (ValidationException $e) { return $this->renderForm($e->getErrors());} catch (UnauthorizedException $e) { return $this->redirectToLogin();}Sıfır Güvenlik
Section titled “Sıfır Güvenlik”Mümkün olduğunda null’dan kaçının:
// Use null object patternpublic function getAuthor(): UserInterface{ return $this->author ?? new AnonymousUser();}
// Use Optional/Maybe patternpublic function findById(int $id): ?Article{ // Explicitly nullable return}database
Section titled “database”Sorgular için Kriterleri Kullan
Section titled “Sorgular için Kriterleri Kullan”$criteria = new CriteriaCompo();$criteria->add(new Criteria('status', 'published'));$criteria->add(new Criteria('category_id', $categoryId));$criteria->setSort('created_at');$criteria->setOrder('DESC');$criteria->setLimit($limit);
$items = $handler->getObjects($criteria);user Girişinden Kaçış
Section titled “user Girişinden Kaçış”$sql = sprintf( "SELECT * FROM %s WHERE id = %d AND title = %s", $db->prefix('mymodule_items'), intval($id), $db->quoteString($title));İşlemleri Kullan
Section titled “İşlemleri Kullan”$db->query('START TRANSACTION');
try { $handler->insert($article); $handler->insert($metadata); $db->query('COMMIT');} catch (\Exception $e) { $db->query('ROLLBACK'); throw $e;}Güvenlik
Section titled “Güvenlik”Girişi Her Zaman Doğrula
Section titled “Girişi Her Zaman Doğrula”use Xmf\Request;
$id = Request::getInt('id', 0);$title = Request::getString('title', '');$data = Request::getArray('data', []);
// Additional validationif (strlen($title) < 5) { throw new ValidationException('Title too short');}CSRF Jetonlarını Kullanın
Section titled “CSRF Jetonlarını Kullanın”// In form$form->addElement(new XoopsFormHiddenToken());
// On submitif (!$GLOBALS['xoopsSecurity']->check()) { redirect_header('index.php', 3, 'Invalid token');}İzinleri Kontrol Et
Section titled “İzinleri Kontrol Et”if (!$helper->isUserAdmin()) { redirect_header('index.php', 3, _NOPERM);}
if (!$permHandler->isGranted('edit', $categoryId)) { throw new UnauthorizedException();}Performans
Section titled “Performans”Önbelleğe Alma Kullan
Section titled “Önbelleğe Alma Kullan”$cache = $helper->getCache();$cacheKey = "articles_{$categoryId}_{$limit}";
$articles = $cache->read($cacheKey);if ($articles === false) { $articles = $handler->getArticles($categoryId, $limit); $cache->write($cacheKey, $articles, 3600);}Sorguları Optimize Edin
Section titled “Sorguları Optimize Edin”// Use indexes// Add to sql/mysql.sql:// INDEX `idx_status_date` (`status`, `created_at`)
// Select only needed columns$handler->getObjects($criteria, false, true); // asArray = true
// Use pagination$criteria->setLimit($perPage);$criteria->setStart($offset);Test etme
Section titled “Test etme”Birim Testlerini Yaz
Section titled “Birim Testlerini Yaz”public function testCreateArticle(): void{ $repository = $this->createMock(ArticleRepositoryInterface::class); $repository->expects($this->once())->method('save');
$service = new ArticleService($repository); $dto = new CreateArticleDTO('Title', 'Content');
$article = $service->create($dto);
$this->assertInstanceOf(Article::class, $article);}İlgili Belgeler
Section titled “İlgili Belgeler”- Temiz Kod - Temiz kod ilkeleri
- Kod-Organizasyon - Proje yapısı
- Test - Test kılavuzu
- ../02-Core-Concepts/Security/Security-Best-Practices - Güvenlik kılavuzu