رفتن به محتوا

بهترین شیوه های توسعه ماژول

این سند بهترین شیوه ها را برای توسعه ماژول های XOOPS با کیفیت بالا ادغام می کند. پیروی از این دستورالعمل ها ماژول های قابل نگهداری، ایمن و عملکردی را تضمین می کند.

معماری پاک را دنبال کنید

Section titled “معماری پاک را دنبال کنید”

کدها را در لایه ها سازماندهی کنید:

src/
├── Domain/ # Business logic, entities
├── Application/ # Use cases, services
├── Infrastructure/ # Database, external services
└── Presentation/ # Controllers, templates

هر کلاس باید یک دلیل برای تغییر داشته باشد:

// Good: Focused classes
class ArticleRepository { /* persistence only */ }
class ArticleValidator { /* validation only */ }
class ArticleNotifier { /* notifications only */ }
// Bad: God class
class Article {
public function save() { }
public function validate() { }
public function notify() { }
public function generatePDF() { }
}

وابستگی ها را تزریق کنید، آنها را ایجاد نکنید:

// Good
public function __construct(
private readonly ArticleRepositoryInterface $repository
) {}
// Bad
public function __construct() {
$this->repository = new ArticleRepository();
}

از انواع دقیق و اعلان‌های نوع استفاده کنید:

<?php
declare(strict_types=1);
final class ArticleService
{
public function findById(int $id): ?Article
{
// ...
}
public function create(CreateArticleDTO $dto): Article
{
// ...
}
}

از استثناها به درستی استفاده کنید:

// Throw specific exceptions
throw new ArticleNotFoundException($id);
throw new ValidationException($errors);
throw new UnauthorizedException('Cannot edit this article');
// Catch at appropriate level
try {
$article = $service->create($dto);
} catch (ValidationException $e) {
return $this->renderForm($e->getErrors());
} catch (UnauthorizedException $e) {
return $this->redirectToLogin();
}

در صورت امکان از null اجتناب کنید:

// Use null object pattern
public function getAuthor(): UserInterface
{
return $this->author ?? new AnonymousUser();
}
// Use Optional/Maybe pattern
public function findById(int $id): ?Article
{
// Explicitly nullable return
}

از معیارها برای کوئری ها استفاده کنید

Section titled “از معیارها برای کوئری ها استفاده کنید”
$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);
$sql = sprintf(
"SELECT * FROM %s WHERE id = %d AND title = %s",
$db->prefix('mymodule_items'),
intval($id),
$db->quoteString($title)
);

از تراکنش ها استفاده کنید

Section titled “از تراکنش ها استفاده کنید”
$db->query('START TRANSACTION');
try {
$handler->insert($article);
$handler->insert($metadata);
$db->query('COMMIT');
} catch (\Exception $e) {
$db->query('ROLLBACK');
throw $e;
}

ورودی را همیشه اعتبارسنجی کنید

Section titled “ورودی را همیشه اعتبارسنجی کنید”
use XMF\Request;
$id = Request::getInt('id', 0);
$title = Request::getString('title', '');
$data = Request::getArray('data', []);
// Additional validation
if (strlen($title) < 5) {
throw new ValidationException('Title too short');
}

از توکن های CSRF استفاده کنید

Section titled “از توکن های CSRF استفاده کنید”
// In form
$form->addElement(new XoopsFormHiddenToken());
// On submit
if (!$GLOBALS['xoopsSecurity']->check()) {
redirect_header('index.php', 3, 'Invalid token');
}
if (!$helper->isUserAdmin()) {
redirect_header('index.php', 3, _NOPERM);
}
if (!$permHandler->isGranted('edit', $categoryId)) {
throw new UnauthorizedException();
}

از حافظه پنهان استفاده کنید

Section titled “از حافظه پنهان استفاده کنید”
$cache = $helper->getCache();
$cacheKey = "articles_{$categoryId}_{$limit}";
$articles = $cache->read($cacheKey);
if ($articles === false) {
$articles = $handler->getArticles($categoryId, $limit);
$cache->write($cacheKey, $articles, 3600);
}
// 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);

تست های واحد را بنویسید

Section titled “تست های واحد را بنویسید”
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);
}
  • Clean-Code - اصول کد پاک
  • Code-Organization - ساختار پروژه
  • تست - راهنمای تست
  • ../02-Core-Concepts/Security/Security-Best-Practices - راهنمای امنیتی