أفضل ممارسات تطوير الوحدات
نظرة عامة
Section titled “نظرة عامة”يوحد هذا المستند أفضل الممارسات لتطوير وحدات XOOPS عالية الجودة. يضمن اتباع هذه الإرشادات وحدات قابلة للصيانة وآمنة وفعالة.
الهندسة المعمارية
Section titled “الهندسة المعمارية”اتبع العمارة النظيفة
Section titled “اتبع العمارة النظيفة”نظم الكود إلى طبقات:
src/├── Domain/ # منطق الأعمال والكيانات├── Application/ # حالات الاستخدام والخدمات├── Infrastructure/ # قاعدة البيانات والخدمات الخارجية└── Presentation/ # المتحكمات والقوالبمسؤولية واحدة
Section titled “مسؤولية واحدة”كل فئة يجب أن تكون لها سبب واحد للتغيير:
// جيد: فئات مركزةclass ArticleRepository { /* الإصرار فقط */ }class ArticleValidator { /* التحقق فقط */ }class ArticleNotifier { /* الإشعارات فقط */ }
// سيء: فئة الإلهclass Article { public function save() { } public function validate() { } public function notify() { } public function generatePDF() { }}حقن الاعتماديات
Section titled “حقن الاعتماديات”اضخ الاعتماديات ولا تنشئها:
// جيدpublic function __construct( private readonly ArticleRepositoryInterface $repository) {}
// سيءpublic function __construct() { $this->repository = new ArticleRepository();}جودة الكود
Section titled “جودة الكود”سلامة النوع
Section titled “سلامة النوع”استخدم النوع الصارم وإعلانات النوع:
<?php
declare(strict_types=1);
final class ArticleService{ public function findById(int $id): ?Article { // ... }
public function create(CreateArticleDTO $dto): Article { // ... }}معالجة الخطأ
Section titled “معالجة الخطأ”استخدم الاستثناءات بشكل صحيح:
// رمي استثناءات محددةthrow new ArticleNotFoundException($id);throw new ValidationException($errors);throw new UnauthorizedException('لا يمكنك تعديل هذا المقال');
// التقط على المستوى المناسبtry { $article = $service->create($dto);} catch (ValidationException $e) { return $this->renderForm($e->getErrors());} catch (UnauthorizedException $e) { return $this->redirectToLogin();}الأمان من القيمة الخالية
Section titled “الأمان من القيمة الخالية”تجنب null حيث أمكن:
// استخدم نمط الكائن الفارغpublic function getAuthor(): UserInterface{ return $this->author ?? new AnonymousUser();}
// استخدم نمط اختياري/ربماpublic function findById(int $id): ?Article{ // عودة قابلة للإلغاء بشكل صريح}قاعدة البيانات
Section titled “قاعدة البيانات”استخدم المعايير للاستعلامات
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);الهروب من مدخلات المستخدم
Section titled “الهروب من مدخلات المستخدم”$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', []);
// التحقق الإضافيif (strlen($title) < 5) { throw new ValidationException('العنوان قصير جداً');}استخدم رموز CSRF
Section titled “استخدم رموز CSRF”// في النموذج$form->addElement(new XoopsFormHiddenToken());
// عند الإرسالif (!$GLOBALS['xoopsSecurity']->check()) { redirect_header('index.php', 3, 'رمز غير صحيح');}تحقق من الأذونات
Section titled “تحقق من الأذونات”if (!$helper->isUserAdmin()) { redirect_header('index.php', 3, _NOPERM);}
if (!$permHandler->isGranted('edit', $categoryId)) { throw new UnauthorizedException();}الأداء
Section titled “الأداء”استخدم التخزين المؤقت
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);}تحسين الاستعلامات
Section titled “تحسين الاستعلامات”// استخدم الفهارس// أضف إلى sql/mysql.sql:// INDEX `idx_status_date` (`status`, `created_at`)
// اختر الأعمدة المطلوبة فقط$handler->getObjects($criteria, false, true); // asArray = true
// استخدم الترقيم$criteria->setLimit($perPage);$criteria->setStart($offset);الاختبار
Section titled “الاختبار”اكتب اختبارات الوحدة
Section titled “اكتب اختبارات الوحدة”public function testCreateArticle(): void{ $repository = $this->createMock(ArticleRepositoryInterface::class); $repository->expects($this->once())->method('save');
$service = new ArticleService($repository); $dto = new CreateArticleDTO('العنوان', 'المحتوى');
$article = $service->create($dto);
$this->assertInstanceOf(Article::class, $article);}الوثائق ذات الصلة
Section titled “الوثائق ذات الصلة”- Clean-Code - مبادئ الكود النظيف
- Code-Organization - هيكل المشروع
- Testing - دليل الاختبار
- ../02-Core-Concepts/Security/Security-Best-Practices - دليل الأمن