در فریمورک فلر، اتصال به دیتابیس از طریق شیء سراسری $db
انجام میشود. این شیء در کنترلرها به کمک متد __construct
مقداردهی میشود. برای نمونه:
namespace Controllers;
class USERS extends BaseController
{
public $db;
public function __construct()
{
global $db;
$this->db = $db;
}
}
با این روش، میتوانید در تمام متدهای کنترلر به دیتابیس دسترسی داشته باشید.
برای افزودن یک رکورد جدید به دیتابیس، به سادگی آرایهای از دادهها را به متد insert
ارسال کنید:
$data = [
"login" => "admin",
"firstName" => "John",
"lastName" => "Doe"
];
$id = $this->db->insert('users', $data);
if ($id) {
echo 'کاربر ایجاد شد. شناسه: ' . $id;
}
در این مثال، اگر عملیات درج موفق باشد، شناسه رکورد ایجاد شده برگردانده میشود.
شما میتوانید از توابع داخلی مانند now()
یا func()
برای پردازش مقادیر قبل از درج استفاده کنید:
$data = [
'login' => 'admin',
'active' => true,
'firstName' => 'John',
'lastName' => 'Doe',
'password' => $this->db->func('SHA1(?)', ['secretpassword+salt']),
'createdAt' => $this->db->now(),
'expires' => $this->db->now('+1Y')
];
$id = $this->db->insert('users', $data);
if ($id) {
echo 'کاربر ایجاد شد. شناسه: ' . $id;
} else {
echo 'درج اطلاعات با خطا مواجه شد: ' . $this->db->getLastError();
}
با این روش میتوانید مقادیری مثل رمز عبور هش شده یا زمان ایجاد/انقضا را مستقیماً در لحظه درج تعیین کنید.
در صورت نیاز به درج یا بروزرسانی خودکار در صورت وجود رکورد مشابه (بر اساس کلید یکتا)، میتوانید از متد onDuplicate
استفاده کنید:
$data = [
"login" => "admin",
"firstName" => "John",
"lastName" => "Doe",
"createdAt" => $this->db->now(),
"updatedAt" => $this->db->now()
];
$updateColumns = ["updatedAt"];
$lastInsertId = "id";
$this->db->onDuplicate($updateColumns, $lastInsertId);
$id = $this->db->insert('users', $data);
با این روش، اگر رکوردی با کلید یکتا از قبل موجود باشد، فقط فیلد updatedAt
بهروزرسانی میشود.
اگر نیاز به درج چندین رکورد به صورت همزمان داشته باشید، میتوانید از متد insertMulti
بهره ببرید:
$data = [
[
"login" => "admin",
"firstName" => "John",
"lastName" => "Doe"
],
[
"login" => "other",
"firstName" => "Another",
"lastName" => "User",
"password" => "very_cool_hash"
]
];
$ids = $this->db->insertMulti('users', $data);
if (!$ids) {
echo 'درج گروهی با خطا مواجه شد: ' . $this->db->getLastError();
} else {
echo 'کاربران جدید با این شناسهها درج شدند: ' . implode(', ', $ids);
}
این روش بهینهتر از اجرای چندین insert
جداگانه است.
اگر تمام رکوردها کلیدهای یکسانی داشته باشند، میتوانید کلیدها را جداگانه مشخص کرده و آرایه دادهها را سادهتر بنویسید:
$data = [
["admin", "John", "Doe"],
["other", "Another", "User"]
];
$keys = ["login", "firstName", "lastName"];
$ids = $this->db->insertMulti('users', $data, $keys);
if (!$ids) {
echo 'درج گروهی با خطا مواجه شد: ' . $this->db->getLastError();
} else {
echo 'کاربران جدید با این شناسهها درج شدند: ' . implode(', ', $ids);
}
متد replace
در فلر همانند insert
عمل میکند، با این تفاوت که در صورت وجود رکورد با کلید یکتا، آن را جایگزین میکند:
$data = [
"id" => 1,
"login" => "admin",
"firstName" => "John",
"lastName" => "Doe"
];
$id = $this->db->replace('users', $data);
if ($id) {
echo 'رکورد جایگزین شد. شناسه: ' . $id;
} else {
echo 'جایگزینی با خطا مواجه شد: ' . $this->db->getLastError();
}
برای بهروزرسانی اطلاعات یک یا چند رکورد، ابتدا شرط مورد نظر را با where
مشخص کنید، سپس دادههای جدید را به update
ارسال کنید:
$data = [
'firstName' => 'Bobby',
'lastName' => 'Tables',
'editCount' => $this->db->inc(2),
'active' => $this->db->not()
];
$this->db->where('id', 1);
if ($this->db->update('users', $data)) {
echo $this->db->count . ' رکورد بهروزرسانی شد';
} else {
echo 'بهروزرسانی با خطا مواجه شد: ' . $this->db->getLastError();
}
همچنین میتوانید تعداد رکوردهای بهروزرسانی شده را با پارامتر limit
محدود کنید:
$this->db->update('users', $data, 10);
// خروجی: UPDATE users SET ... LIMIT 10
برای دریافت دادهها از دیتابیس، میتوانید از متد get
استفاده کنید. پس از اجرا، تعداد رکوردهای بازیابی شده در متغیر $count
ذخیره میشود:
$users = $this->db->get('users'); // دریافت تمام کاربران
$users = $this->db->get('users', 10); // دریافت 10 کاربر
همچنین میتوانید فقط ستونهای خاصی را انتخاب کنید:
$cols = ["id", "name", "email"];
$users = $this->db->get('users', null, $cols);
if ($this->db->count > 0) {
foreach ($users as $user) {
print_r($user);
}
}
برای دریافت تنها یک رکورد:
$this->db->where('id', 1);
$user = $this->db->getOne('users');
echo $user['id'];
و برای دریافت نتایج محاسباتی (مثل مجموع یا شمارش):
$stats = $this->db->getOne('users', 'sum(id), count(*) as cnt');
echo "مجموع کاربران: " . $stats['cnt'];
دریافت یک مقدار خاص (مانند شمارش تعداد کل کاربران):
$count = $this->db->getValue('users', 'count(*)');
echo "{$count} کاربر ثبت شده است";
دریافت یک ستون خاص از چندین رکورد:
$logins = $this->db->getValue('users', 'login', null);
foreach ($logins as $login) {
echo $login;
}
برای بارگذاری دادههای یک فایل CSV به جدول خاصی:
$path_to_file = "/home/john/file.csv";
$this->db->loadData("users", $path_to_file);
همچنین میتوانید تنظیمات بیشتری هنگام بارگذاری مشخص کنید:
$options = [
"fieldChar" => ';',
"lineChar" => '\r\n',
"linesToIgnore" => 1
];
$this->db->loadData("users", "/home/john/file.csv", $options);
استفاده از LOAD DATA LOCAL
نیز پشتیبانی میشود:
$options = [
"fieldChar" => ';',
"lineChar" => '\r\n',
"linesToIgnore" => 1,
"loadDataLocal" => true
];
$this->db->loadData("users", "/home/john/file.csv", $options);
برای بارگذاری دادههای یک فایل XML:
$path_to_file = "/home/john/file.xml";
$this->db->loadXML("users", $path_to_file);
با امکان تعیین تنظیمات اضافه:
$options = [
"linesToIgnore" => 0,
"rowTag" => ""
];
$this->db->loadXML("users", "/home/john/file.xml", $options);
برای دریافت نتایج به صورت صفحهبندی شده، از متد paginate
استفاده کنید:
$page = 1;
$this->db->pageLimit = 2;
$products = $this->db->arraybuilder()->paginate("products", $page);
echo "نمایش صفحه $page از " . $this->db->totalPages;
میتوانید نتایج را بر اساس یک کلید مشخص، به صورت آرایه انجمنی (Associative Array) دریافت کنید:
$user = $this->db->map('login')->ObjectBuilder()->getOne('users', 'login, id');
print_r($user);
// خروجی نمونه:
// [
// "user1" => 1
// ]
اگر بیش از دو ستون انتخاب شود، خروجی به صورت آبجکت خواهد بود:
$user = $this->db->map('login')->ObjectBuilder()->getOne('users', 'id, login, createdAt');
print_r($user);
// خروجی نمونه:
// [
// "user1" => (object) [
// "id" => 1,
// "login" => "user1",
// "createdAt" => "2015-10-22 22:27:53"
// ]
// ]
در فریمورک فلر، نتایج دیتابیس میتوانند به سه فرمت مختلف بازگردند: آرایه از آرایهها، آرایه از آبجکتها، یا رشتهی JSON. برای تعیین نوع بازگشتی میتوانید از متدهای ArrayBuilder()
، ObjectBuilder()
و JsonBuilder()
استفاده کنید.
نکته: حالت پیشفرض ArrayBuilder()
است.
// آرایهای
$u = $this->db->getOne('users');
echo $u['login'];
// آبجکت
$u = $this->db->ObjectBuilder()->getOne('users');
echo $u->login;
// رشتهی JSON
$json = $this->db->JsonBuilder()->getOne('users');
echo $json;
برای اجرای مستقیم کوئریهای SQL، میتوانید از متد rawQuery
استفاده کنید:
$users = $this->db->rawQuery('SELECT * FROM users WHERE id >= ?', [10]);
foreach ($users as $user) {
print_r($user);
}
$user = $this->db->rawQueryOne('SELECT * FROM users WHERE id=?', [10]);
echo $user['login'];
// به صورت آبجکت
$user = $this->db->ObjectBuilder()->rawQueryOne('SELECT * FROM users WHERE id=?', [10]);
echo $user->login;
$password = $this->db->rawQueryValue('SELECT password FROM users WHERE id=? LIMIT 1', [10]);
echo "رمز عبور: {$password}";
نکته: برای بازگرداندن یک رشته به جای آرایه، باید LIMIT 1
در انتهای کوئری قرار بگیرد.
$logins = $this->db->rawQueryValue('SELECT login FROM users LIMIT 10');
foreach ($logins as $login) {
echo $login;
}
$params = [1, 'admin'];
$users = $this->db->rawQuery('SELECT id, firstName, lastName FROM users WHERE id = ? AND login = ?', $params);
print_r($users);
// اجرای کوئریهای پیچیدهتر
$params = [10, 1, 10, 11, 2, 10];
$q = "(
SELECT a FROM t1 WHERE a = ? AND B = ? ORDER BY a LIMIT ?
) UNION (
SELECT a FROM t2 WHERE a = ? AND B = ? ORDER BY a LIMIT ?
)";
$results = $this->db->rawQuery($q, $params);
print_r($results);
متدهای where()
، orWhere()
، having()
و orHaving()
به شما امکان میدهند شرطهای WHERE و HAVING را راحتتر و خواناتر ایجاد کنید.
// شرطهای ساده
$this->db->where('id', 1);
$this->db->where('login', 'admin');
$results = $this->db->get('users');
// یا با لود زنجیرهای
$results = $this->db->where('id', 1)
->where('login', 'admin')
->get('users');
// شرطهای Having
$this->db->where('id', 1);
$this->db->having('login', 'admin');
$results = $this->db->get('users');
// اشتباه
$this->db->where('lastLogin', 'createdAt');
// درست
$this->db->where('lastLogin = createdAt');
$results = $this->db->get('users');
// بزرگتر مساوی
$this->db->where('id', 50, '>=');
$results = $this->db->get('users');
$this->db->where('id', [4, 20], 'BETWEEN');
$results = $this->db->get('users');
$this->db->where('id', [1, 5, 27, -1, 'd'], 'IN');
$results = $this->db->get('users');
$this->db->where('firstName', 'John');
$this->db->orWhere('firstName', 'Peter');
$results = $this->db->get('users');
$this->db->where('lastName', null, 'IS NOT');
$results = $this->db->get('users');
$this->db->where('fullName', 'John%', 'LIKE');
$results = $this->db->get('users');
$this->db->where('id != companyId');
$this->db->where('DATE(createdAt) = DATE(lastLogin)');
$results = $this->db->get('users');
$this->db->where('(id = ? OR id = ?)', [6, 2]);
$this->db->where('login', 'mike');
$res = $this->db->get('users');
برای دریافت تعداد کل نتایج بدون نیاز به کوئری جداگانه، از withTotalCount()
استفاده کنید:
$offset = 10;
$count = 15;
$users = $this->db->withTotalCount()->get('users', [$offset, $count]);
echo "نمایش {$count} کاربر از مجموع {$this->db->totalCount} کاربر";
برای اضافه کردن کلیدواژههای MySQL مانند LOW PRIORITY
، HIGH PRIORITY
، IGNORE
و ... به متدهای insert()
، replace()
، update()
، delete()
یا get()
میتوانید از setQueryOption()
استفاده کنید.
// درج با LOW_PRIORITY
$this->db->setQueryOption('LOW_PRIORITY')->insert('users', $data);
// انتخاب با FOR UPDATE
$this->db->setQueryOption('FOR UPDATE')->get('users');
همچنین میتوانید چندین کلیدواژه را به صورت آرایه تعیین کنید:
$this->db->setQueryOption(['LOW_PRIORITY', 'IGNORE'])->insert('users', $data);
در SELECT هم میتوانید از این روش استفاده کنید:
$this->db->setQueryOption('SQL_NO_CACHE')->get('users');
برای مرتبسازی نتایج میتوانید از متد orderBy()
استفاده کنید.
$this->db->orderBy('id', 'asc');
$this->db->orderBy('login', 'desc');
$this->db->orderBy('RAND()');
$results = $this->db->get('users');
برای مرتبسازی طبق مقادیر خاص:
$this->db->orderBy('userGroup', 'ASC', ['superuser', 'admin', 'users']);
$this->db->get('users');
اگر از setPrefix()
استفاده کردهاید، نام جداول را داخل backtick (`
) قرار دهید:
$this->db->setPrefix('t_');
$this->db->orderBy('`users`.id', 'asc');
$this->db->get('users');
برای گروهبندی نتایج از متد groupBy()
استفاده کنید.
$this->db->groupBy('name');
$results = $this->db->get('users');
برای اتصال جداول میتوانید از متد join()
استفاده کنید.
$this->db->join('users u', 'p.tenantID = u.tenantID', 'LEFT');
$this->db->where('u.id', 6);
$products = $this->db->get('products p', null, 'u.name, p.productName');
$this->db->join('users u', 'p.tenantID = u.tenantID', 'LEFT');
$this->db->joinWhere('users u', 'u.tenantID', 5);
$products = $this->db->get('products p', null, 'u.name, p.productName');
$this->db->join('users u', 'p.tenantID = u.tenantID', 'LEFT');
$this->db->joinOrWhere('users u', 'u.tenantID', 5);
$products = $this->db->get('products p', null, 'u.productName');
با متد copy()
میتوانید خصوصیات کوئری (مثل where) را در چند عملیات جداگانه به اشتراک بگذارید.
$this->db->where('agentId', 10);
$this->db->where('active', true);
// کپی خصوصیات
$customers = $this->db->copy();
$res = $customers->get('customers', [10, 10]); // LIMIT 10, 10
// ادامه کار با کوئری اصلی
$cnt = $this->db->getValue('customers', 'count(id)');
echo "Total customers: ";
برای ایجاد Subquery میتوانید از متد subQuery()
استفاده کنید.
// بدون alias
$sq = $this->db->subQuery();
$sq->get('users');
// با alias
$sq = $this->db->subQuery('sq');
$sq->get('users');
$ids = $this->db->subQuery();
$ids->where('qty', 2, '>');
$ids->get('products', null, 'userId');
$this->db->where('id', $ids, 'IN');
$res = $this->db->get('users');
$userIdQ = $this->db->subQuery();
$userIdQ->where('id', 6);
$userIdQ->getOne('users', 'name');
$data = [
'productName' => 'test product',
'userId' => $userIdQ,
'lastUpdated' => $this->db->now()
];
$id = $this->db->insert('products', $data);
$usersQ = $this->db->subQuery('u');
$usersQ->where('active', 1);
$usersQ->get('users');
$this->db->join($usersQ, 'p.userId = u.id', 'LEFT');
$products = $this->db->get('products p', null, 'u.login, p.productName');
برای بررسی وجود یا عدم وجود دادهای از کوئریهای فرعی (SubQuery) میتوانید از شرط EXISTS
استفاده کنید:
$sub = $this->db->subQuery();
$sub->where("company", 'testCompany');
$sub->get("users", null, 'userId');
$this->db->where(null, $sub, 'exists');
$products = $this->db->get("products");
// خروجی SQL:
// SELECT * FROM products WHERE EXISTS (SELECT userId FROM users WHERE company='testCompany')
متد has()
بررسی میکند که آیا حداقل یک ردیف مطابق با شرطهای مشخص شده وجود دارد یا خیر.
$this->db->where("user", $user);
$this->db->where("password", md5($password));
if ($this->db->has("users")) {
return "You are logged";
} else {
return "Wrong user/password";
}
$this->db->disconnect();
if (!$this->db->ping()) {
$this->db->connect();
}
$this->db->get('users');
echo "Last executed query was " . $this->db->getLastQuery();
توجه: این متد برای دیباگ کاربرد دارد و ممکن است کوئری تولید شده، به دلیل نبود کوتیشن دور متغیرها، مستقیم قابل اجرا نباشد.
if ($this->db->tableExists('users')) {
echo "hooray";
}
$escaped = $this->db->escape("' and 1=1");
تراکنشها فقط روی جداول InnoDB پشتیبانی میشوند.
$this->db->startTransaction();
if (!$this->db->insert('myTable', $insertData)) {
// در صورت خطا، تغییرات اعمال شده را لغو میکنیم
$this->db->rollback();
} else {
// موفقیتآمیز
$this->db->commit();
}
بعد از اجرای هر کوئری میتوانید خطاها را بررسی کنید.
$this->db->where('login', 'admin')->update('users', ['firstName' => 'Jack']);
if ($this->db->getLastErrno() === 0) {
echo 'Update successful';
} else {
echo 'Update failed. Error: ' . $this->db->getLastError();
}
با فعال کردن setTrace(true)
میتوانید مدت زمان اجرای هر کوئری را ردیابی کنید.
$this->db->setTrace(true);
$this->db->get("users");
$this->db->get("test");
print_r($this->db->trace);
// خروجی نمونه:
[
[0] => [
'SELECT * FROM t_users ORDER BY `id` ASC',
0.0010669231414795,
'MysqliDb->get() >> file "/path/tests.php" line #151'
],
[1] => [
'SELECT * FROM t_test',
0.00069189071655273,
'MysqliDb->get() >> file "/path/tests.php" line #152'
]
]
برای قفل کردن جداول از متد lock()
همراه با setLockMethod()
استفاده میشود.
$this->db->setLockMethod("WRITE")->lock("users");
$this->db->setLockMethod("READ")->lock(["users", "log"]);
$this->db->unlock();