لایه پایگاه داده
🗄️ لایه پایگاه داده
Section titled “🗄️ لایه پایگاه داده”2.5.x ✅ 4.0.x ✅
درک انتزاع پایگاه داده XOOPS، ماندگاری شی و ساخت پرس و جو.
:::tip [دسترسی به داده های خود را اثبات کنید] الگوی handler/Criteria در هر دو نسخه کار می کند. برای آماده شدن برای XOOPS 4.0، دستههای بسته بندی را در کلاسهای مخزن برای آزمایشپذیری بهتر در نظر بگیرید. انتخاب الگوی دسترسی به داده را ببینید. :::
بررسی اجمالی
Section titled “بررسی اجمالی”لایه پایگاه داده XOOPS یک انتزاع قوی بر روی MySQL/MariaDB ارائه می دهد که شامل:
- ** الگوی کارخانه ** - مدیریت اتصال پایگاه داده متمرکز
- نگاشت شی - رابطه ای - XoopsObject و هندلرها
- ساخت پرس و جو - سیستم معیاری برای پرس و جوهای پیچیده
- اتصال استفاده مجدد - اتصال تک از طریق کارخانه تک تن (نه ادغام)
🏗️ معماری
Section titled “🏗️ معماری”flowchart TB subgraph App["📱 Application Code"] AppCode["Your Module Code"] end
subgraph Handler["🔧 XoopsPersistableObjectHandler"] HandlerMethods["create() | get() | insert() | delete()<br/>getObjects() | getCount() | deleteAll()"] end
subgraph Object["📦 XoopsObject"] ObjectMethods["initVar() | getVar() | setVar() | toArray()"] end
subgraph Criteria["🔍 Criteria System"] CriteriaMethods["Criteria | CriteriaCompo | CriteriaElement"] end
subgraph Database["🗄️ XoopsDatabase"] DatabaseMethods["query() | queryF() | fetchArray() | insert()"] end
subgraph Storage["💾 MySQL / MariaDB"] DB[(Database)] end
App --> Handler Handler --> Object Object --> Criteria Criteria --> Database Database --> Storage
style App fill:#e3f2fd,stroke:#1976d2 style Handler fill:#e8f5e9,stroke:#388e3c style Object fill:#fff3e0,stroke:#f57c00 style Criteria fill:#f3e5f5,stroke:#7b1fa2 style Database fill:#fce4ec,stroke:#c2185b style Storage fill:#eceff1,stroke:#546e7a🔌 اتصال به پایگاه داده
Section titled “🔌 اتصال به پایگاه داده”دریافت اتصال
Section titled “دریافت اتصال”// Recommended: Use the global database instance$db = \XoopsDatabaseFactory::getDatabaseConnection();
// Legacy: Global variable (still works)global $xoopsDB;XoopsDatabaseFactory
Section titled “XoopsDatabaseFactory”الگوی کارخانه تضمین می کند که از یک اتصال پایگاه داده واحد استفاده مجدد می شود:
<?php
class XoopsDatabaseFactory{ private static ?XoopsDatabase $instance = null;
public static function getDatabaseConnection(): XoopsDatabase { if (self::$instance === null) { self::$instance = new XoopsMySQLDatabase(); } return self::$instance; }}📦 XoopsObject
Section titled “📦 XoopsObject”کلاس پایه برای تمام اشیاء داده در XOOPS.
تعریف یک شی
Section titled “تعریف یک شی”<?php
namespace XoopsModules\MyModule;
class Article extends \XoopsObject{ public function __construct() { $this->initVar('article_id', \XOBJ_DTYPE_INT, null, false); $this->initVar('category_id', \XOBJ_DTYPE_INT, 0, true); $this->initVar('title', \XOBJ_DTYPE_TXTBOX, '', true, 255); $this->initVar('content', \XOBJ_DTYPE_TXTAREA, '', false); $this->initVar('author_id', \XOBJ_DTYPE_INT, 0, true); $this->initVar('status', \XOBJ_DTYPE_TXTBOX, 'draft', true, 20); $this->initVar('views', \XOBJ_DTYPE_INT, 0, false); $this->initVar('created', \XOBJ_DTYPE_INT, time(), false); $this->initVar('updated', \XOBJ_DTYPE_INT, 0, false); }}انواع داده
Section titled “انواع داده”| ثابت | نوع | توضیحات |
|---|---|---|
XOBJ_DTYPE_INT | عدد صحیح | مقادیر عددی |
XOBJ_DTYPE_TXTBOX | رشته | متن کوتاه (< 255 نویسه) |
XOBJ_DTYPE_TXTAREA | متن | محتوای متن طولانی |
XOBJ_DTYPE_EMAIL | ایمیل | آدرس های ایمیل |
XOBJ_DTYPE_URL | آدرس اینترنتی | آدرس های وب |
XOBJ_DTYPE_FLOAT | شناور | اعداد اعشاری |
XOBJ_DTYPE_ARRAY | آرایه | آرایه های سریالی |
XOBJ_DTYPE_OTHER | مختلط | داده های خام |
کار با اشیا
Section titled “کار با اشیا”// Create new object$article = new Article();
// Set values$article->setVar('title', 'My Article');$article->setVar('content', 'Article content here...');$article->setVar('category_id', 5);$article->setVar('author_id', $xoopsUser->getVar('uid'));
// Get values$title = $article->getVar('title'); // Raw value$titleDisplay = $article->getVar('title', 'e'); // For editing (HTML entities)$titleShow = $article->getVar('title', 's'); // For display (sanitized)
// Bulk assign from array$article->assignVars([ 'title' => 'New Title', 'status' => 'published']);
// Convert to array$data = $article->toArray();🔧 کنترل کننده اشیا
Section titled “🔧 کنترل کننده اشیا”XoopsPersistableObjectHandler
Section titled “XoopsPersistableObjectHandler”کلاس handler عملیات CRUD را برای نمونه های XoopsObject مدیریت می کند.
<?php
namespace XoopsModules\MyModule;
class ArticleHandler extends \XoopsPersistableObjectHandler{ public function __construct(\XoopsDatabase $db = null) { parent::__construct( $db, 'mymodule_articles', // Table name Article::class, // Object class 'article_id', // Primary key 'title' // Identifier field ); }}روش های هندلر
Section titled “روش های هندلر”// Get handler instance$articleHandler = xoops_getModuleHandler('article', 'mymodule');
// Create new object$article = $articleHandler->create();
// Get by ID$article = $articleHandler->get(123);
// Insert (create or update)$success = $articleHandler->insert($article);
// Delete$success = $articleHandler->delete($article);
// Get multiple objects$articles = $articleHandler->getObjects($criteria);
// Get count$count = $articleHandler->getCount($criteria);
// Get as array (key => value)$list = $articleHandler->getList($criteria);
// Delete multiple$deleted = $articleHandler->deleteAll($criteria);روش های کنترل کننده سفارشی
Section titled “روش های کنترل کننده سفارشی”<?php
namespace XoopsModules\MyModule;
class ArticleHandler extends \XoopsPersistableObjectHandler{ // ... constructor
/** * Get published articles */ public function getPublished(int $limit = 10, int $start = 0): array { $criteria = new \CriteriaCompo(); $criteria->add(new \Criteria('status', 'published')); $criteria->setSort('created'); $criteria->setOrder('DESC'); $criteria->setLimit($limit); $criteria->setStart($start);
return $this->getObjects($criteria); }
/** * Get articles by category */ public function getByCategory(int $categoryId, int $limit = 10): array { $criteria = new \CriteriaCompo(); $criteria->add(new \Criteria('category_id', $categoryId)); $criteria->add(new \Criteria('status', 'published')); $criteria->setSort('created'); $criteria->setOrder('DESC'); $criteria->setLimit($limit);
return $this->getObjects($criteria); }
/** * Get articles by author */ public function getByAuthor(int $authorId): array { $criteria = new \Criteria('author_id', $authorId); return $this->getObjects($criteria); }
/** * Increment view count */ public function incrementViews(int $articleId): bool { $sql = sprintf( 'UPDATE %s SET views = views + 1 WHERE article_id = %d', $this->table, $articleId ); return $this->db->queryF($sql) !== false; }
/** * Get popular articles */ public function getPopular(int $limit = 5): array { $criteria = new \CriteriaCompo(); $criteria->add(new \Criteria('status', 'published')); $criteria->setSort('views'); $criteria->setOrder('DESC'); $criteria->setLimit($limit);
return $this->getObjects($criteria); }}🔍 سیستم معیار
Section titled “🔍 سیستم معیار”سیستم Criteria روشی قدرتمند و شی گرا برای ساخت بندهای SQL WHERE ارائه می دهد.
معیارهای اساسی
Section titled “معیارهای اساسی”// Simple equality$criteria = new \Criteria('status', 'published');
// With operator$criteria = new \Criteria('views', 100, '>=');
// Column comparison$criteria = new \Criteria('updated', 'created', '>');CriteriaCompo (معیارهای ترکیبی)
Section titled “CriteriaCompo (معیارهای ترکیبی)”$criteria = new \CriteriaCompo();
// AND conditions (default)$criteria->add(new \Criteria('status', 'published'));$criteria->add(new \Criteria('category_id', 5));
// OR conditions$criteria->add(new \Criteria('featured', 1), 'OR');
// Nested conditions$subCriteria = new \CriteriaCompo();$subCriteria->add(new \Criteria('author_id', 1));$subCriteria->add(new \Criteria('author_id', 2), 'OR');$criteria->add($subCriteria);مرتب سازی و صفحه بندی
Section titled “مرتب سازی و صفحه بندی”$criteria = new \CriteriaCompo();$criteria->add(new \Criteria('status', 'published'));
// Sorting$criteria->setSort('created');$criteria->setOrder('DESC');
// Multiple sort fields$criteria->setSort('category_id, created');$criteria->setOrder('ASC, DESC');
// Pagination$criteria->setLimit(10); // Items per page$criteria->setStart(20); // Offset
// Group by$criteria->setGroupby('category_id');اپراتورها
Section titled “اپراتورها”| اپراتور | مثال | خروجی SQL |
|---|---|---|
= | new Criteria('status', 'published') | status = 'published' |
!= | new Criteria('status', 'draft', '!=') | status != 'draft' |
> | new Criteria('views', 100, '>') | views > 100 |
>= | new Criteria('views', 100, '>=') | views >= 100 |
< | new Criteria('views', 100, '<') | views < 100 |
<= | new Criteria('views', 100, '<=') | views <= 100 |
LIKE | new Criteria('title', '%php%', 'LIKE') | title LIKE '%php%' |
NOT LIKE | new Criteria('title', '%test%', 'NOT LIKE') | title NOT LIKE '%test%' |
IN | new Criteria('id', '(1,2,3)', 'IN') | id IN (1,2,3) |
NOT IN | new Criteria('id', '(1,2,3)', 'NOT IN') | id NOT IN (1,2,3) |
مثال پیچیده
Section titled “مثال پیچیده”// Find published articles in specific categories,// with search term in title, sorted by views$criteria = new \CriteriaCompo();
// Status must be published$criteria->add(new \Criteria('status', 'published'));
// In categories 1, 2, or 3$criteria->add(new \Criteria('category_id', '(1, 2, 3)', 'IN'));
// Title contains search term$searchTerm = '%' . $db->escape($searchQuery) . '%';$criteria->add(new \Criteria('title', $searchTerm, 'LIKE'));
// Created in last 30 days$thirtyDaysAgo = time() - (30 * 24 * 60 * 60);$criteria->add(new \Criteria('created', $thirtyDaysAgo, '>='));
// Sort by views descending$criteria->setSort('views');$criteria->setOrder('DESC');
// Paginate$criteria->setLimit(10);$criteria->setStart($page * 10);
$articles = $articleHandler->getObjects($criteria);$totalCount = $articleHandler->getCount($criteria);📝 سوالات مستقیم
Section titled “📝 سوالات مستقیم”برای پرس و جوهای پیچیده که با معیارها امکان پذیر نیست، از SQL مستقیم استفاده کنید.
سوالات ایمن (خوانده)
Section titled “سوالات ایمن (خوانده)”$db = \XoopsDatabaseFactory::getDatabaseConnection();
$sql = sprintf( 'SELECT a.*, c.category_name FROM %s a LEFT JOIN %s c ON a.category_id = c.category_id WHERE a.status = %s ORDER BY a.created DESC LIMIT %d', $db->prefix('mymodule_articles'), $db->prefix('mymodule_categories'), $db->quoteString('published'), 10);
$result = $db->query($sql);
while ($row = $db->fetchArray($result)) { // Process row echo $row['title'];}پرس و جو بنویسید
Section titled “پرس و جو بنویسید”// Insert$sql = sprintf( "INSERT INTO %s (title, content, created) VALUES (%s, %s, %d)", $db->prefix('mymodule_articles'), $db->quoteString($title), $db->quoteString($content), time());$db->queryF($sql);$newId = $db->getInsertId();
// Update$sql = sprintf( "UPDATE %s SET views = views + 1 WHERE article_id = %d", $db->prefix('mymodule_articles'), $articleId);$db->queryF($sql);$affectedRows = $db->getAffectedRows();
// Delete$sql = sprintf( "DELETE FROM %s WHERE article_id = %d", $db->prefix('mymodule_articles'), $articleId);$db->queryF($sql);فرار از ارزش ها
Section titled “فرار از ارزش ها”// String escaping$safeString = $db->quoteString($userInput);// or$safeString = $db->escape($userInput);
// Integer (no escaping needed, just cast)$safeInt = (int) $userInput;⚠️ بهترین شیوه های امنیتی
Section titled “⚠️ بهترین شیوه های امنیتی”همیشه از ورودی کاربر فرار کنید
Section titled “همیشه از ورودی کاربر فرار کنید”// NEVER do this$sql = "SELECT * FROM articles WHERE title = '$_GET[title]'"; // SQL Injection!
// DO this$title = $db->escape($_GET['title']);$sql = "SELECT * FROM articles WHERE title = '$title'";
// Or better, use Criteria$criteria = new \Criteria('title', $db->escape($_GET['title']));استفاده از پرس و جوهای پارامتری (XMF)
Section titled “استفاده از پرس و جوهای پارامتری (XMF)”use XMF\Database\TableLoad;
// Safe bulk insert$tableLoad = new TableLoad('mymodule_articles');$tableLoad->insert([ ['title' => 'Article 1', 'content' => 'Content 1'], ['title' => 'Article 2', 'content' => 'Content 2'],]);انواع ورودی را اعتبارسنجی کنید
Section titled “انواع ورودی را اعتبارسنجی کنید”use XMF\Request;
$id = Request::getInt('id', 0, 'GET');$title = Request::getString('title', '', 'POST');📊 نمونه طرحواره پایگاه داده
Section titled “📊 نمونه طرحواره پایگاه داده”-- sql/mysql.sql
CREATE TABLE `{PREFIX}_mymodule_articles` ( `article_id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, `category_id` INT(11) UNSIGNED NOT NULL DEFAULT 0, `title` VARCHAR(255) NOT NULL DEFAULT '', `content` TEXT, `author_id` INT(11) UNSIGNED NOT NULL DEFAULT 0, `status` VARCHAR(20) NOT NULL DEFAULT 'draft', `views` INT(11) UNSIGNED NOT NULL DEFAULT 0, `created` INT(11) UNSIGNED NOT NULL DEFAULT 0, `updated` INT(11) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (`article_id`), KEY `category_id` (`category_id`), KEY `author_id` (`author_id`), KEY `status` (`status`), KEY `created` (`created`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;🔗 مستندات مرتبط
Section titled “🔗 مستندات مرتبط”#xoops #پایگاه داده #orm #معیارها #handlers #mysql