تابع set_charset() در PHP
در ارتباط با پایگاه داده MySQL، تعیین صحیح character set و collation برای جلوگیری از مشکلهای نمایش کاراکتر (مثل «موجیکابِک» یا نشاندادن علامت سؤال) حیاتی است. در PHP، یکی از راههای استاندارد برای تنظیم مجموعه کاراکتر اتصال به MySQL استفاده از تابع set_charset() (یا تابع معادل mysqli_set_charset()) است. این تابع تضمین میکند که متن ارسالی و دریافتی بین PHP و MySQL به درستی رمزگذاری/رمزگشایی شود.
چرا set_charset مهم است؟
- جلوگیری از مشکلهایی مانند کاراکترهای نامفهوم یا علامت سؤال در خروجی.
- پشتیبانی از کاراکترهای چهار بایتی مانند ایموجیها با استفاده از utf8mb4.
- هماهنگسازی client و server برای جلوگیری از double-encoding.
روشهای تنظیم charset در PHP
معمولاً سه روش برای تنظیم charset وجود دارد:
- استفاده از mysqli->set_charset یا تابع mysqli_set_charset (توصیهشده)
- اجرای کوئری SQL:
SET NAMES '...' COLLATE ... - برای PDO، تعیین charset در DSN یا اجرای کوئری SET NAMES
مثال OOP با mysqli (توصیهشده)
$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');
if ($mysqli->connect_errno) {
die('Connect error: ' . $mysqli->connect_error);
}
if (!$mysqli->set_charset('utf8mb4')) {
die('Error loading character set utf8mb4: ' . $mysqli->error);
}در این قطعه کد اتصال به دیتابیس برقرار شده و بلافاصله پس از اتصال، set_charset('utf8mb4') فراخوانی میشود. اگر بارگذاری charset با خطا مواجه شود، پیام خطا چاپ میشود. این روش باعث میشود متغیرهای داخلی MySQL (مثل character_set_client و character_set_results) به درستی تنظیم شوند.
مثال پراسسدورال با mysqli
$link = mysqli_connect('localhost', 'user', 'pass', 'dbname');
if (!$link) {
die('Connect error: ' . mysqli_connect_error());
}
if (!mysqli_set_charset($link, 'utf8mb4')) {
die('Error loading character set utf8mb4: ' . mysqli_error($link));
}همان عملکرد قبلی در سبک تابعی را نشان میدهد. نکته مهم این است که set_charset حتماً بعد از اتصال و پیش از اجرای هر query فراخوانده شود.
استفاده در PDO
$dsn = "mysql:host=localhost;dbname=dbname;charset=utf8mb4";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'"
];
$pdo = new PDO($dsn, 'user', 'pass', $options);در PDO بهتر است charset را در DSN مشخص کنید. استفاده از MYSQL_ATTR_INIT_COMMAND اجازه میدهد مقدارهای اولیه مانند SET NAMES اجرا شوند. اگر DSN فاقد charset باشد، ممکن است نیاز به اجرای دستی SET NAMES باشد اما این روش به اندازه set_charset() در mysqli ایمن نیست زیرا پیوند بین client API و تنظیمات MySQL ممکن است متفاوت باشد.
مقایسه set_charset و SET NAMES
| روش | مزایا | معایب |
|---|---|---|
| mysqli->set_charset() | تنظیم مستقیم در client API، قابل اعتماد برای prepared statements | محدود به mysqli |
| SET NAMES ‘charset’ | ساده و کارا؛ با هر رابطی قابل اجرا | ممکن است تنظیمات client API را کامل انجام ندهد؛ ریسک خطا در برخی سناریوها |
| PDO DSN charset | ساده در راهاندازی، مناسب برای PDO | در نسخههای قدیمی PHP با برخی درایورها مشکل داشت |
نکات فنی و بهترینروشها
- همیشه از utf8mb4 به جای utf8 پیشفرض MySQL استفاده کنید تا از ایموجیها و کاراکترهای چهار بایتی پشتیبانی شود.
- پس از اتصال، فوراً set_charset را فراخوانی کنید، قبل از اینکه هر query یا prepared statement ارسال شود.
- مطمئن شوید جداول و ستونهای دیتابیس نیز از همان charset/collation استفاده کنند (مثلاً
utf8mb4_unicode_ci). - برای بررسی وضعیت میتوانید کوئریهای زیر را اجرا کنید:
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';این کوئریها مقادیر فعلی charset و collation را روی سرور نمایش میدهند و کمک میکنند منبع مشکل را پیدا کنید.
رفع مشکلات رایج (mojibake و double-encoding)
- اگر متنها به صورت رشتههای escape یا علامت سؤال نمایش داده میشوند: احتمالاً charset بین PHP و MySQL یکسان نیست.
- اگر پیغامهای فارسی داخل جدول درست ذخیره میشوند ولی در مرورگر اشتباه نشان داده میشوند: مشکل ممکن است در headers یا
<meta charset="utf-8">صفحه باشد. - در صورتی که دادهها از ابتدا در دیتابیس اشتباه ذخیره شدهاند (double-encoded)، باید دادهها را export کرده، charset صحیح اعمال و مجدد import کنید یا از اسکریپتهایی برای تصحیح encoding بهره ببرید.
جمعبندی کوتاه
تابع set_charset() ابزار ساده و مؤثری برای همسانسازی encoding بین PHP و MySQL است و جلوگیری از مشکلات نمایش کاراکتر را به همراه دارد. استفاده از utf8mb4 توصیه میشود و همیشه set_charset را بلافاصله پس از برقرار کردن اتصال فراخوانی کنید. در پروژههای جدید مطمئن شوید جداول و اتصال هر دو از یک charset و collation واحد استفاده میکنند.
آیا این مطلب برای شما مفید بود ؟



