شنبه ۲۲ شهریور ۱۴۰۴

Saturday, September 13, 2025 GMT +3:30

آموزش MySQL، سیستم مدیریت پایگاه داده

mysql

ذخیره اطلاعات به صورت دسته بندی شده و دسترسی سریع به آنها ضرورتی بود که باعث ایجاد سیستم های مدیریت پایگاه داده رابطه ای (Relational Database Management System یا به اختصار RDBMS) در دنیای برنامه نویسی و به تبع برنامه نویسی وب شد، اگر یک برنامه نویس PHP باشیم و بخواهیم به طور مثال سرویس فرهنگ لغات آنلاین طراحی کنیم، قاعدتا اولین مشکلی که با آن روبرو خواهیم شد این است که لغات را در کجا ذخیره و چگونه آنها را فراخوانی کنیم، چگونه کلمه مورد نظر کاربر را از بین کلمات موجود جستجو کرده و نتیجه را پس از پردازش به صفحه مرورگر ارسال نمائیم و سوالاتی از این دست، لذا ناگزیر بحث استفاده از یک سیستم مدیریت پایگاه داده جهت ذخیره، جستجو، انتخاب، ویرایش و حذف اطلاعات مطرح می شود که در وب و بخصوص برای برنامه نویسان PHP اولین و شاید بهترین انتخاب MySQL باشد، اینکه چرا و چگونه از MySQL در کدنویسی PHP خود استفاده کنیم، مبحثی است که در سلسله آموزش های مقدماتی پیش رو به آن خواهیم پرداخت.

MySQL چیست و چه کاربردی دارد؟


قبل از هر چیز بهتر است به این سوال پاسخ دهیم که MySQL چیست و چه کاربردی دارد؟ در پاسخ می توان گفت که MySQL یکی از پرکاربردترین سیستم های متن باز (Open-source) مدیریت پایگاه داده است که توسط شرکت سوئدی MySQL AB ایجاد و اولین نسخه آن در سال 1995 معرفی شد (مالکیت شرکت MySQL AB در حال حاضر در اختیار شرکت Oracle است)، SQL در واقع زبانی است که برای استفاده در سیستم های مدیریت پایگاه داده رابطه ای (RDBMS) طراحی شده و عبارت MySQL اشاره به این زبان دارد، در واقع MySQL برای اجرای دستورات ما مانند دستور ساخت جدول، ذخیره، جستجو، انتخاب، ویرایش و حذف اطلاعات از زبان SQL استفاده می کند و لذا آشنایی قبلی با SQL می تواند فراگیری کار با MySQL را بیش از پیش ساده کند، از آنجایی که این سیستم مدیریت پایگاه داده جزئی از خانواده موسوم به LAMP (مخفف Linux, Apache, MySQL, Perl/PHP/Python) است لذا بیشترین سازگاری و کارایی را در این حیطه دارد و انتخاب اول برنامه نویسان PHP به حساب می آید، با MySQL می توانیم اطلاعات مورد نظر را در دیتابیسی که در سرور ایجاد می کنیم ذخیره کرده آنها را بر طبق اهداف برنامه به صورت حرفه ای دسته بندی و هر زمان نیاز بود در اطلاعات جستجو نموده و مقادیر دلخواه را استخراج نمائیم، این قابلیت ها برای طراحی برنامه های داینامیک وب جزء ملزومات اولیه هستند و MySQL به خوبی این نیازها را پوشش می دهد، استفاده سایت های معروفی مانند Google، Facebook، Twitter، Flicker و YouTube از این پایگاه داده نشان دهنده حرفه ای و کارآمد بودن آن است.

ساختار کلی و نحوه دسته بندی اطلاعات در پایگاه داده


همان طور که اشاره شد پایگاه داده جزء کلیدی در برنامه های کاربردی تحت وب محسوب می شود و لذا شناخت ساختار کلی و نحوه دسته بندی اطلاعات در آن اهمیت ویژه ای دارد، در MySQL هر پایگاه داده (Database) یک نام بخصوص دارد و حداقل از یک جدول (Table) اطلاعاتی تشکیل شده است، جداول نیز خود شامل زیر مجموعه هایی هستند که به آنها ستون (Column) می گویند که سطرح های اطلاعات (Rows) را در خود جای می دهند، به طور مثال دیتابیس زبان های برنامه نویسی می تواند شامل جدول برنامه نویسی دسکتاپ، برنامه نویسی موبایل و برنامه نویسی وب باشد، به همین صورت هر جدول می تواند شامل ستون (Column) و سطرها (Rows) باشد، سطرح ها در واقع همان ردیف های اطلاعات هستند که در جدول برای هر ستون ذخیره می شوند (تصویر زیر):
MySQL Database Structure
در نمونه ساختار فوق programming نام دیتابیس، desktop نام جدول و id، name و status ستون های دیتابیس هستند که سطرح های اطلاعاتی را شامل می شوند (نام دیتابیس، جدول و ستون ها در مثال فرضی و به تعداد دلخواه می باشند).

مدیریت پایگاه داده MySQL با phpMyAdmin


برنامه نویسان PHP معمولا از دو طریق می توانند به سیستم مدیریت پایگاه داده MySQL دسترسی داشته باشند، با استفاده از برنامه phpMyAdmin و همچنین با کدنویسی PHP، برنامه phpMyAdmin جهت مدیریت به اصطلاح دستی MySQL و اعمال تغییراتی مانند ساخت پایگاه داده جدید، ساخت جداول، ستون ها، تغییر ویژگی های جداول و ستون ها و مواردی از این دست کاربرد دارد و تقریبا هر کاربری با هر سطح از آشنایی با برنامه نویسی می تواند با محیط آن ارتباط برقرار کرده و نیازهای خود را مرتفع کند، phpMyAdmin در واقع برنامه ای نوشته شده به PHP با هدف مدیریت پایگاه داده با استفاده از رابط کاربری ساده و تحت مرورگر است تا هم انجام موارد اولیه، برپایی پایگاه داده و اعمال تغییرات بعدی در آن آسان و روند کار تسریع شود و هم کاربران مختلف با هر سطح از آشنایی با PHP بتوانند بدون دغدغه و احیانا نگرانی از سردرگمی، با محیط MySQL ارتباط برقرار کنند، به هر صورت برای آشنایی بیشتر می توانیم به سایت مرجع این برنامه مراجعه کنیم:
https://www.phpmyadmin.net
همچنین می توانیم با پیش نمایشی از این برنامه در آدرس زیر کار کنیم که برای شروع امکان بسیار خوبی است:
https://demo.phpmyadmin.net/master-config
یادآور می شویم که این برنامه معمولا به صورت از پیش نصب شده در سرورهای لینوکس یا برنامه های سرور مجازی (Localhost) وجود دارد و کافی است از پنل مدیریت هاست سایت یا از طریق آدرس 
localhost/phpmyadmin
در لوکال به آن دسترسی پیدا کنیم، در برنامه های سرور مجازی معمولا با نام کاربری root و بدون پسورد می توانیم وارد محیط برنامه phpMyAdmin شویم.

ارتباط PHP با پایگاه داده MySQL


همان طور که اشاره شد با کدنویسی PHP می توانیم به پایگاه داده MySQL دسترسی داشته و بین کدهای PHP با سیستم مدیریت پایگاه داده MySQL ارتباط برقرار کنیم، این قابلیت باعث می شود بتوانیم برنامه های حرفه ای تحت وب که معمولا نیازمند نگهداری داده ها در یک بانک اطلاعاتی مطمئن هستند را طراحی و عملیاتی از قبیل ذخیره سازی، دسته بندی، جستجو، انتخاب، ویرایش و حذف ردیف ها را به صورت سیستماتیک و با کمک دستورات برنامه نویسی انجام دهیم، به طور مثال کاربر می تواند در فیلد جستجوی برنامه تحت وب عبارت مورد نظر خود را وارد کرده و ما با دستورات PHP به MySQL می گوییم که ردیف های متناسب با کلمه درخواستی کاربر را انتخاب و به عنوان نتیجه به مفسر PHP برگرداند، در ادامه نتیجه دریافتی را با کدنویسی PHP تجزیه تحلیل نموده و خروجی نهایی را مطابق هدف برنامه به کاربر نشان دهیم، این ارتباط با کمک برنامه هایی تحت عنوان اکستنشن (Extension) صورت می گیرد، اکستنش ها در واقع بسته های نرم افزاری هستند که به هسته PHP امکان انجام عملیات های خاص مانند اتصال و مدیریت پایگاه داده را می دهند، در PHP برای این منظور پیشتر از اکستنشن قدیمی MySQL استفاده می شد که در نسخه 7 PHP منسوخ و به صورت پیش فرض حذف شده است و توصیه می شود برای برنامه های جدید اکستنشن MySQLi یا PDO را جایگزین آن نمائیم.
نکته: سیستم مدیریت پایگاه داده MySQL با اکستنشن MySQL دو عبارت مجزا هستند!
       PHP <===> MySQL
- MySQL (Deprecated - منسوخ شده)
- MySQLi (Recommended - توصیه شده)
- PDO (Recommended - توصیه شده)

چرا از اکستنشن MySQLi یا PDO استفاده کنیم؟


اکستنشن MySQLi (حرف i پایانی مخفف improved) نسخه بهبود یافته از اکستنشن MySQL بوده و شیوه نگارش دستورات آن در حالت برنامه نویسی رویه ای شباهت زیادی به شیوه نگارش دستورات MySQL دارد، همچنین MySQLi اکستنشن اختصاصی PHP برای کار با سیستم مدیریت پایگاه داده MySQL بوده و بیشترین سازگاری را با امکانات آن دارد، با توجه به این دلایل در آموزش های پیش رو از این اکستنشن در مثال ها استفاده خواهیم کرد، PDO (مخفف PHP Data Objects) اکستنشن دیگری است که می تواند جایگزین MySQL شود، PDO اکستنشن غیراختصاصی PHP برای کار با پایگاه داده و از جمله پایگاه داده MySQL است، این اکستنشن در مقایسه با MySQLi سازگاری کمتری با امکانات سیستم مدیریت پایگاه داده MySQL دارد اما به لحاظ حجم کم (Lightweight)، حرفه ای بودن و امکان کار با سیستم های مختلف پایگاه داده می تواند در برنامه های تحت وب گزینه مناسبی باشد، توسعه دهندگان PHP در نسخه های جدید استفاده از اکستنشن MySQL را توصیه نمی کنند و آن را به حالت Deprecated درآورده اند که یعنی استفاده از آن توصیه نمی شود و حتی از نسخه PHP 7 به بعد دیگر این اکستنشن در مفسر PHP به صورت پیش فرض وجود ندارد، دلیل این موضوع رشد امکانات و قابلیت های PHP در طی سالیان گذشته و قدیمی شدن اکستنشن MySQL در طی این فرآیند است، همچنین قابلیت های زیادی به سیستم مدیریت پایگاه داده MySQL اضافه شده است که با اکستنشن قدیمی MySQL امکان استفاده بهینه از آنها وجود ندارد، به طور مثال در بخش حفظ امنیت برنامه های نوشته شده به زبان PHP استفاده از این اکستنشن باید با دقت و تسلط کافی صورت گیرد تا با حملات موسوم به SQL Injection روبرو نشویم که این با هدف استفاده همگان از PHP در تضاد است و در اکستنشن های جدید (MySQLi و PDO) امنیت کدهای PHP به شکل محسوسی بهبود یافته، همچنین نگهداری فنی و ایجاد تغییرات بعدی در برنامه های نوشته شده با اکستنشن MySQL در مقایسه با اکستنشن های جدید به نسبت زمانبر و حساستر است.
نکته: در طراحی ساختار برنامه ها می توانیم با جدا کردن بخش اجرای پرس و جوهای دیتابیس، امکانی در نظر بگیریم که کاربر به دلخواه خود اکستنشن مورد نظر را انتخاب کند، قاعدتا این کار صرفا جنبه تزئینی ندارد و در مواردی که یک اکستشن به هر دلیل کارایی ندارد می تواند راهگشا باشد.

پشتیبانی MySQLi از برنامه نویسی رویه ای و شی گرا


اکستنشن MySQLi از دو شیوه برنامه نویسی رویه ای (Procedural) و شی گرا (Object-oriented) پشتیبانی می کند، در این سری از آموزش ها نمونه کدها هم به شیوه رویه ای و هم به شیوه شی گرا ارائه می شوند، یادآور می شویم که دو روش در عمل کارکرد مشابه دارند و تفاوت در نحوه کدنویسی و مدیریت ساختار برنامه است، هرچند بحث در مورد تفاوت برنامه نویسی رویه ای و شی گرا باید در جای خود بررسی شود اما در یک تحلیل ساده معمولا از کدنویسی رویه ای برای نوشتن برنامه ها و پروژه های کوچک به عنوان روش به اصطلاح دم دستی استفاده می شود و برنامه نویسی شی گرا برای ایجاد ساختارهای پیچیده تر و نوشتن برنامه هایی با جزئیات بیشتر کاربرد دارد، خوشبختانه PHP در این زمینه سخاوتمند است و حق انتخاب را به کاربران می دهد، توصیه ما این است که ضمن فراگیری روش رویه ای به عنوان شیوه پایه و مقدماتی، پروژه های کاربردی و پر جزئیات خود را به روش شی گرا (OOP یا Object-oriented programming) بنویسیم.
دسته بندی: آموزش مقدماتی » MySQL
related مطالب بیشتر:
توابع تجمیعی (Aggregate Functions) در MySQL
محدودسازی، گروه بندی و مرتب سازی نتایج در MySQL
ساخت دیتابیس، جدول و ستون با دستور CREATE در MySQL
نحوه ذخیره کردن اطلاعات با دستور INSERT در MySQL
استفاده از WHERE در پرس و جوی MySQL
دیدگاه
more ۸۰ دیدگاه برای این مطلب ارسال شده است.
more چینش دیدگاه ها به ترتیب از جدیدترین به قدیمی ترین است.
سینا
۰۸:۴۴ ۱۴۰۱/۱۱/۰۶
با سلام و درود
من چهار تا داده به شیوه زیر دارم
date.    user.       id
1399 3. 1
1381 2. 2
1379. 3. 3
1380. 2. 4
میخوام با php کوچکترین تاریخ هر دو کاربر ۲ و ۳ رو همزمان با هم دربیارم!
با تشکر
با نمونه پرس و جوی زیر می توانید دو ردیف با کمترین مقدار را هم زمان از دیتابیس MySQL استخراج کنید:
SELECT MIN(`date`), `date` FROM `tbl_name` WHERE `user` = '2' 
UNION
SELECT MIN(`date`), `date` FROM `tbl_name` WHERE `user` = '3'
سینا
۲۰:۵۵ ۱۴۰۱/۱۰/۲۹
با سلام و با تشکر از شما
از لطف و محبت شما بسیار ممنون و سپاسگزارم ببخشید این چند خیلی پیام دادم و مزاحم شدم بلاخره درست شد و همونی که میخواستم شد من مثل ابوریحانی بیرونی هستم وقتی سوالی برام پیش میاد ول کنش نیستم تا جوابش رو بدست نیارم!
اون لحظه حتی دوست ندارم بمیرم دیشب کلا نخوابیدم و تا ساعت ۹ که نت قطع کردن همش درگیر جواب بودم بعد نت رو واسه کنکور قطع کردن جواب شمارو که دیدم تونستم نمونه کدهای خودم رو با پاسخ شما هماهنگ کنم و بلاخره مشکلم حل شد. ۱۵ هزار تا مطلب بود که تایمشون بروز شد.
از لطف و محبت شما بسیار ممنون و سپاسگزارم
انشاءالله جایگاهتون وسط بهشت باشه
در پناه خدای بزرگ باشید
خواهش، نظر لطف شما است، خوشحالیم که مشکل رفع شد.
سینا
۰۱:۰۵ ۱۴۰۱/۱۰/۲۹
با سلام و درود
من یه کد نوشتم که برای id های پشت سر هم جواب میده و زمان رو برام تغییر میده وقتی آیدی ها پشت سر هم هستند راحت میشه زمان آیدی قبلی رو پیدا کرد در این حالت زمان قبلی رو با شناسه ایدی این مطلب منهای عدد 1 بدست میارم و عمل جمع رو براش انجام میده ولی یه مشکل دارم در صورتی که شناسه ها پشت سر هم نباشن به مشکل می خورم چون نمی تونم شناسه ایدی قبلی رو پیدا کنم و زمانش رو دربیارم و امکان داره شناسه آیدی قبل از اون مطلب که متعلق به همون کاربر است هزار تا با شناسه این فرق داشته باشه
به صورت زیر
id      user      time
33. 2. 12345
34. 3. 12365
35. 4. 14325
36. 3. 65424
37. 2 12375
38. 2. 32431
یه بار برای شناسه های پشت سر هم کدی که نوشتم عمل کرد ولی برای بدست آوردن زمان شناسه هایی که پشت سر هم نیستند به مشکل خوردم.
به نظر بعد از بدست آوردن شناسه آخرین و بزرگترین ID باید در حلقه شناسه های قبلی را بدست آورید و برای هر کدام که فیلد آن در دیتابیس وجود داشت عملیات (افزایش، کاهش) را انجام دهید، در واقع برای مدیریت این چرخه مقدار آخرین ID، مقدار ID فعلی، مقدار ID بعدی و شماره دور حلقه مورد نیاز است، چیزی شبیه نمونه کدهای زیر:
$all_id_sql = "SELECT id FROM tbl WHERE user = 2 ORDER BY id DESC";
$main_query = mysqli_query($conn, $all_id_sql);
$loop = 1;

while($row = mysqli_fetch_array($main_query)){
if($loop == 1){
$last_id = $row['id'];
$current_id = $last_id;
} else {
$current_id = $last_id - ($last_id - $row['id']);
}

$next_id = $current_id - 1;

$check_id_sql = "SELECT id FROM tbl WHERE id = $next_id AND user = 2 LIMIT 1";
$check_query = mysqli_query($conn, $check_id_sql);
$count = mysqli_num_rows($check_query);
if($count > 0){
//next id exist, run update query
}

$loop++;
}
الگوریتم را بر مبنای آخرین ID یا اولین ID می توانیم توسعه دهیم که نمونه بالا از بزرگتر به کوچکتر است، برای تست فرض می کنیم 10 بزرگترین آی دی ما است و در حلقه برای شماره های فرضی قبلی 7، 4 و 2 را در نظر می گیریم و عملیات کد را ذهنی شبیه سازی و مرور می کنیم.
سینا
۰۴:۵۶ ۱۴۰۱/۱۰/۲۸
باسلام مجدد و درود برشما
واسه مطالب جدید راحته آخرین مطلب رو با کوئری زدن توی دیتابیس پیدا کنم و برای مطلب بعدش آپدیت بنویسم. واسه مطالب قبلی باید اولین مطلب رو پیدا کنم و بعد به زمان بعدی ها اضافه کنم. واسه همین تایمهارو قبل از اجرای دستور یکی می کنم و با اینکار یه داده ثابت دارم و می تونم مشخص کنم هر آیدی که از اولین آیدی بزرگتر باشه و تایمش برابر با تایم ثابت باشه 3600 ثانیه از ایدی قبل از خودش بهش اضافه بشه که این حلقه باز پشت سر هم تکرار نشه. بعد از اجرای دستور تایمی که از اول ثابت بوده و کوئری روش اجرا شده دیگه اون تایم ثابت رو نداره و معلوم میشه بهش اضافه شده و دیگه ثابت نیست!
id      time
1. 1234567890
2. 1234567890
3. 1234567890
4. 1234567890
5. 1234567890
الان من باید اولین آیدی رو پیدا کنم که تایمش ثابته بعد بگم اگه ایدی کوچکتر نداره ولی آیدی بزرگتر از خودش داره تایم زمان آیدی قبل از خودش رو پیدا کنه. و اگه تایم آیدی قبلی ثابت نبود بهش 3600 ثانیه اضافه کنه.
الگوریتمش روی کاغذ همین میشه فقط نمی دونم چرا انقد گیجم کرده شاید چون نمی تونم بخاطر سردرد تمرکز بگیرم!
گاهی کمی دور شدن از فضای برنامه نویسی و کلا سیستم به بازیابی تمرکز و رفع گره های برنامه ها کمک می کند! به تجربه در یک جدول آزمایشی با ردیف های کمتر مرحله به مرحله الگوریتم را کدنویسی و تست کنید کار راحتتر می شود.
سینا
۱۳:۴۵ ۱۴۰۱/۱۰/۲۷
با تشکر از شما استاد بزرگوارم
اینو شب تست می کنم من واسه آپدیت کردن تایم لازم دارم توضیح کامل به اینصورت:
واسه زمان مطالب بالای هزار تا عنوان، id ها با هم فرق می کنه، واسه مطالب جدید اون روز که راهنمایی کردید با php درست کردم این دستور رو برای مطالب قبلی لازم دارم مطالب قبلی هرچی فکر می کنم راه حلش رو پیدا نمی کنم که چطوری زمان آیدی مطلب قبلی رو بگیرم و به تعدادی که میخوام به زمان مطلب بعدی اضافه کنم مطالب جدید تایم آخرین مطلب رو می گیرم و اندازه مثلا 3600 ثانیه بهش اضافه می کنم که میشه یه ساعت واسه اینکار اول همه ی زمانها رو تبدیل به زمان حال می کنم الان همه ی زمانها با هم یکی هستند بعد از این باید اولین مطلب به زمانش 120 تا اضافه بشه و به زمانهای بعدی هر کدام 120 تا بیشتر از زمان آیدی قبلی اضافه بشه
بک آپ می گیرم و دستورات رو شبها که خلوته اجرا می کنم
به نظر برای اجرای بهینه آپدیت ها برنامه را با PHP بنویسید و به امکانات MySQL صرف اکتفا نکنید، با PHP مطالب را در حلقه استخراج کنید و پس از اعمال تغییرات روی مقادیر ستون ها مجدد ردیف مورد نظر را آپدیت کنید، اگر روی کاغذ الگوریتم و مراحل کار را بنویسید در نوشتن کدهای برنامه نهایی و پیدا کردن راه حل کمک می کند.
سینا
۱۷:۵۳ ۱۴۰۱/۱۰/۲۶
با سلام و درود بر شما
راهی هست توی mysql من داده های یک جدول رو که عددی هستند به صورت زیر آپدیت کنم! میخواهم همه ی داده های یک جدول رو هر جدول 120 اضافه کنم
داده اول 120
داده دوم 240
داده سومی 360
داده چهارمی 440
یعنی به هر فیلد 120 تا 120 تا اضافه کنم که هر فیلد 120 تا با فیلد قبل از خودش تفاوت داشته باشه!
با تشکر فراوان
اگر درست متوجه منظورتان شده باشیم می توانید پرس و جو را به شکل زیر اجرا کنید:
UPDATE tbl_name SET col_1 = 120, col_2 = col_1 + 120, col_3 = col_2 + 120 WHERE 1 = 1
نکته: روش بالا تست نشده، لطف ابتدا در حالت آزمایشی بررسی و پس از گرفتن پشتیبان از اطلاعات موجود از نمونه پرس و جوی بالا در جداول اصلی استفاده کنید.
mahdi
۱۰:۵۰ ۱۴۰۰/۰۷/۰۷
استاد کامنتی که پذیرفته نشده چه نیازی داره نگهش داریم ؟
مثلا برا پست خوبه حذفی ها رو تا 30 روز نگه داریم اما برا کامنت بهتر نیست کلا حذف شن؟
و استاد من دسته بندی ها رو بعنوان منوی اصلی سایت در نظر گرفته بودم و برای هر کدوم یه استاتوس در نظر گرفته بودم که در منو نمایش داده بشن یا نه ولی به گفته شما نباید این کارو کنم و باید یه ماژول منوساز داشته باشم و دسته بندی ها رو کلا یه حالت دیگه نمایش بدم؟
این موارد عموما سلیقه ای هستند و بر اساس نیاز و انتظار شما از برنامه CMS لحاظ می شوند، هیچ اجباری به نگهداری نیست منتها حذف با تاخیر هم مشکلی برای سیستم ایجاد نمی کند و در مواردی ممکن است برای پیگیری مدیر سایت کاربرد داشته باشد، خیلی از مواقع حذف ها ناشی از عجله و تصمیم زودهنگام است!
در مورد دسته بندی هم اگر ماژول اختصاصی تعریف کنید که خیلی بهتر است، ما چون خودمان از CMS استفاده می کنیم برنامه را خیلی ماژولار طراحی نکرده ایم.
mahdi
۱۸:۱۳ ۱۴۰۰/۰۷/۰۶
سلام استاد عزیز،
استاد من برای بخش دیدگاه ها سه حالت در نظر گرفتم و از سافت دلیت هم استفاده کردم
- فهرست دیدگاه های در انتظار تایید - تایید شده - حذف شده
بعد خودم فکر میکنم نباید از سافت دلیت استفاده کنم و زمانیکه یه دیدگاه حذف میشه باید دیگه کلا حذف شه چون کار بیخودیه نگهش داریم، درست میگم؟ و فکر میکنم بخش سوم که فهرست دیدگاه های حذف شده هست رو کلا ننویسمش و فقط فهرست دیدگاه های در انتظار تایید و تایید شده رو نگه دارم؟ توی فهرست دیدگاه های حذف شده قرار دادم که بشه دیدگاه رو کلا حذف کرد یا به تایید نشده برش گردوند ولی فکر میکنم کارم اشتباهه و اصلا این بخش نباید باشه
نظر شما چیه استاد عزیز
خیلی ممنون
وجود بخش برای برگدان اطلاعات حذف شده می تواند یک مزیت باشد، در سیستم فعلی سایت حذف ها همیشگی هستند اما در سیستم جدید تا 30 روز نگهداری و سپس به صورت کامل حذف می شوند.
mahdi
۱۸:۲۳ ۱۴۰۰/۰۷/۰۵
استاد اگر مثلا یه دسته بندی حذف بشه و باعث شه یه پست که فقط همین دسته بندی رو داشته بدون دسته بندی بشه ، چیزی که به فکرم رسید اینه که اولا خب مهم نیست دسته بندی نداشته باشه و دوم اینکه یه دسته بندی پیشفرض بزارم برا همچین مواقعی که پست هایی که دسته بندیشون کلا حذف میشه برن تو این دسته ؟ همچین چیزی هست استاد اگه هست معمولا اسم اون دسته بندی رو چی میزارن؟ و بنظر شما کدوم بهتره یعنی پست بدون دسته بندی باشه مهم نیست یا باید یه پیش فرضی بهش داد؟
خیلی ممنون استاد عزیز
معمولا دسته بندی را خود کاربر باید تعیین کند، سیستم می تواند چنین قابلیتی داشته باشد که پست بدون دسته بندی امکانش فراهم باشد یا خیر وگرنه کاربر می تواند یک دسته بندی به فرض "عمومی" در نظر بگیرد و این پست ها را منتقل کند، ما در سیستم سایت اجازه حذف دسته بندی که پست فعال دارند را نمی دهیم و قبل حذف کاربر باید این موارد را تغییر دهد، البته می شود یک ساز کار برای تغییر دسته جمعی دسته بندی ها تعریف کرد.
البته همه این موارد سلیقه ای هستند و در عمل ممکن است روش بهتری جایگزین شود.
mahdi
۱۶:۱۷ ۱۴۰۰/۰۷/۰۵
استاد عزیز این متد دلیت یه دسته بندی هستش که آخر این شکلی نوشتمش ، هر دسته بندی که میخواد حذف بشه به همراه زیر دسته هاش حذف میشه و اگر سطح پایین باشه که فقط خودش حذف میشه نه سطح بالاییا
public function destroy($id){
$ykId = [];
$doId = [];
$seId = [];
$sup = Category::find($id);
array_push($ykId,$sup->id);
if($sup){
$subStep = $sup->children()->get();
foreach($subStep as $sb){
array_push($doId,$sb->id);
if($subStep){
$undersubStep = $sb->children()->get();
foreach($undersubStep as $usb){
array_push($seId,$usb->id);
}
}
}
}
$ids = array_merge($ykId,$doId,$seId);
foreach($ids as $id){
$imgCat = Category::find($id);
unlink(trim($imgCat->thumb['img'],"/"));
cfSet();
Category::delete($id);
}
$rLike = ",".implode(",|,",$ids).",";
$repleft = '';
$repright = '';
foreach($ids as $id){
$repleft .= "REPLACE(";
$repright .= ", ',".$id."', '') ";
}
$end = $repleft."cat_id".$repright;
cfSet();
Post::isqry("UPDATE `posts` SET cat_id = $end WHERE id IN (SELECT id FROM `posts` WHERE cat_id RLIKE '$rLike')");
echoJsonTrue(["دسته بندی بصورت دائمی حذف گردید"]);
}
که دسته بندی ها رو در هر پست با این کوئری آخر پاک میکنه حالا خب ممکنه ده هزارتا پست باشه که یکی از دسته بندی هاش باید پاک بشه پس رو ده هزارتا رکورد تاثیر میزاره و فکر میکنم این یه حالت داخلی داشته باشه که مای اسکوئل تو خودش حلش میکنه و مشکلی نداره چندتا رکورد باشه تا اینکه همه پستارو یبار سلکت کنم بعد تقسیم بندی کنم و مثلا هر هزارتا رکورد یک بار کوئری بزنم که پاک بشن ، و اینکه استاد این برای دسته بندی هاست و زیاد فکر نکنم کسی هی بخواد حذف و اضافه کنه و زمانیکه تعداد پست ها زیاد شن دیگه اون ادمین حتما به یه ثباتی رسیده تو موضوعات کارش و اگرم نرسیده دیگه اصلا دیتابیسش بترکه بهتره والا :))) نظر شما چیه استاد بزرگ
زمانی هم که میخوام دسته بندی های یه پست رو ذخیره کنم به این شکل ابتدا و انتهاش یه کاما قرار میدم که زمان حذف با دقت بیشتری بتونم ریپلیس و حذفش کنم
$inputs['cat_id'] = ",".implode(',',$inputs['cat_id']).",";
استاد یه سوالم دارم برای منوی سایت میدونم که میشه کلا یه منوی اختصاصی درست کرد ولی میخوام بدونم یعنی تا جایی که میدونم منوی اصلی سایت ها همین دسته بندی ها هستن ، آیا باید ماژول جداگانه ای برای منو درست کنم یا همین دسته بندی ها بمونن؟
خیلی ممنون استاد عزیز
می توانیم پرس و جو را با درج قید محدود کنیم به فرض دسته بندی بالاترین سطح و یک سطح کمتر در ستون های مجزا برای هر پست درج شوند و موقع حذف یا ویرایش در قسمت WHERE ستون ها را لحاظ کنیم به این صورت ردیف های درگیر به حداقل ممکن کاهش می یابند.
در مورد منو بستگی دارد چه انتظاری از منوسازتان داشته باشید، ماژول منو را می شود خیلی ساده یا با امکان تعریف آدرس های دلخواه یا ترکیب این دو حالت تعریف کرد، می توانید با حالت ساده شروع کنید و در نسخه های بعد آن را توسعه دهید.
mahdi
۱۸:۴۹ ۱۴۰۰/۰۷/۰۴
سلام استاد عزیز ، استاد مشکلم در پیدا کردن رکوردهای مورد نظر نیست الان سرچ کردم و به تابع ریپلیس در sql رسیدم که میتونه کاری که میخوامو برام انجام بده ولی یکم پیچیدگی داره و میخوام همین کاری که شما گفتین رو انجام بدم و رکوردها رو بکشم بیرون و با php روی فیلدی که میخوام حذف و اضافه انجام بدم و بعد دوباره رکورد رو آپدیت کنم اونوقت این از لحاظ پرفرمنس بد نمیشه؟ حتی اگر هزاران رکورد باشه بازم مشکلی نیست تو این کار و کلا مرسومه بین همه ؟
خیلی ممنون استاد بزرگ
درضمن بله استاد عزیز روش بهینه واس ماس :) خیلی مخلصیم
حفظ پرفرمنس بستگی به این دارد چطور ساختار به کدها مرتبط شود و چقدر دیتابیس را درگیر فرآیندها کنید، در هر روشی اگر ساختار و کدنویسی درست نباشد پرفرمنس زیر سوال می رود، معمولا رابط کاربری برنامه باید طوری باشد که 1000 رکورد در یک درخواست ویرایش نشوند! در واقع با بهینه ترین روش ها هم اگر 1000 رکورد را درگیر در پردازش کنید به همان نسبت اجرای کل برنامه کند می شود، باید از حداکثر قواعدی که می شود در عین حفظ کارایی برنامه سرعت اجرای آن را افزایش داد استفاده کنیم به فرض سیستم Index در دیتابیس خودش 90 درصد خیلی از این سبک مشکلات را حل می کند! در اینکه این روش مرسوم است یا خیر بررسی نداشته ایم اما وردپرس شبیه این ساز و کار را استفاده می کند، باز خودتان بررسی کنید اگر نتیجه جدید پیدا کردید لطفا به اشتراک بگذارید :)
mahdi
۱۷:۳۶ ۱۴۰۰/۰۷/۰۴
سلام استاد عزیز یه سوال درباره حذف دسته بندی ها دارم سیستم دسته بندیها سه سطحیه یعنی یه سرگروه یه زیرگروه یه زیرگروه دیگه
سردسته : آموزش php آیدی : 1
زیر دسته : mvc آیدی : 2 پرنت آیدی : 1
زیر دسته : category آیدی : 3 پرنت آیدی :2
هزار تا پست داریم
پست یک ------- cat_id : 1,3,4,5,7,9
پست یک ------- cat_id : 4,6,2,5,1,8
پست یک ------- cat_id : 3,5,7,1
حالا من این سردسته رو دلیت میکنم
آموزش php آیدی : 1
و دوتای بعدیشم پیرو سردستشون دلیت میشن حالا به چه شکلی از فیلد کت آیدی پست ها آیدی های این کتگوری های حذف شده (1 و 2 و 3) رو پاک کنم؟ یا کلا راه بهتری هست ؟
خیلی ممنون استاد عزیز
یک روش برای مدیریت این حالت استفاده از REGEXP برای پیدا کردن آی دی های بینابینی در پرس و جوی MySQL است، در صورتی هم که از Prepared Statements استفاده کنیم می توانیم CONCAT را با تابع REGEXP ترکیب کنیم، به فرض:
REGEXP CONCAT('^(.*)',?, '(.*)')
آی دی را پیدا که کردیم کل مقدار ستون را استخراج و بعد از اعمال تغییرات مجدد آپدیت می کنیم، البته ما در CMS خودمان از روش سطوح ثابت (بخش، مجموعه و سه سطح زیر مجموعه) استفاده کرده ایم و برای هر سطح یک ستون در نظر گرفته ایم که مدیریت این موارد ساده تر باشد (روش بهینه روش شما است).
محمدباقر حسیبیان
۱۶:۴۲ ۱۳۹۹/۰۴/۰۶
من این مشکل برام پیش اومده که موقع ورود به پروژه م توی لوکال هاست wamp صفحه سفیده و هیچی رو نشون نمیده و کد سایت هم هیچ مشکلی نداره
قاعدتا هیچ مشکلی بی دلیل نیست اما باید با خطایابی مرحله به مرحله ایراد را پیدا کرد، رفع مشکل نیاز به دسترسی و تست پروژه در سیستمتان دارد که در صورت تمایل می توانید برنامه Team Viewer را نصب و از طریق ایمیل سایت (موجود در بخش تماس) اطلاع دهید تا با تعیین زمان قبلی پروژه بررسی شود.
مهدی
۱۹:۱۵ ۱۳۹۸/۱۰/۰۲
سلام و درود
مهندس جان در حال حاضر collation مربوط به دیتابیس و جدول و ستون های مربوطه همش utf8_persian_ci هستش.
وقتی
SHOW VARIABLES LIKE 'collation%';
رو اجرا میکنم خروجی زیر رو دارم
collation_connection=utf8_general_ci
collation_database = utf8_persian_ci
collation_server = latin1_swedish_ci
طبق راهنمایی شما برای اینکه collation_server رو عوض کنم collation_server = utf8_persian_ci و character_set_server=utf8 رو به my.cnf اضافه کردم. منتها مشکلی که پیش اومد این بود که تمام مقادیر فارسی داخل دیتابیس وقتی نمایش داده میشند حروف درهم ریخته نشون میده.
یا وقتی داخل فایل connection به دیتابیس دستورات زیر را میزنم باز مقادیر فارسی دیتابیس رو درهم ریخته نشون میده
$connect=new PDO($dsn,$user,$pass);	
$connect->exec("SET NAMES utf8");
نیازی به اعمال تغییر در فایل my.cnf نیست! سعی کنید در برنامه phpMyAdmin یک دیتابیس جدید به صورت utf8_persian_ci ایجاد کنید، جداول و ستون ها هم به همین صورت تعریف شوند، سپس اطلاعات فعلی را با PHP استخراج کنید و در جدول جدید INSERT نمائید، اگر همه چیز درست باشد اطلاعات باید به صورت خوانا و فارسی در برنامه phpMyAdmin دیده شوند، در غیر اینصورت قسمتی را اشتباه انجام می دهید، برای تست به جای اطلاعات موجود یک متن ساده را از فرم HTML دریافت و INSERT کنید، در صورتی که اطلاعات به صورت مستقیم به درستی درج شوند باید اطلاعات ناخوانا را ابتدا از فیلتر توابع مربوط به یونیکد مانند iconv عبور دهید (نیاز به تست و آزمایش و خطا است).
کلا مشکل مطرح شده با ناسازگاری یونیکد ذخیره سازی و بازیابی است که اگر مراحل گفته شده را انجام دهید قابل رفع است، در صورت تداوم مشکل ممکن است نیاز به بررسی از طریق برنامه TeamViewer باشد!
مهدی
۲۱:۴۰ ۱۳۹۸/۱۰/۰۱
مهندس تلاش زیادی کردم که رکوردها رو با distinct بدون تکرار در بیارم، مثلا دستورات زیر رو اجرا کردم
UPDATE  article_journals SET article_title = REPLACE(article_title, 'ff', 'ff') WHERE article_title LIKE '%ff%';
UPDATE articles SET article_title = REGEXP_REPLACE(article_title, ' \+', ' ')
ولی باز یکسری مشکلات دیگه وجود داره که DISTINCT تعداد خالص رو بهم نمیده، مثلا ممکنه داخل متن عنوان مقاله یه نقطه اضافه یا کاراکتر های مثل – وجود داشته باشه یا اینکه ممکنه بعضی از حروف عنوان مقاله capital نوشته شده باشه (من موقع ذخیره to lower نکردم و ...) با این حال من قصد دارم از تابع similar_text استفاده کنم تا درصد تشابه یک مقاله رو با بقیه مقالات بدست بیارم و اونایی که مثلا بیش از 90 درصد تشابه دارند رو تکراری تشخیص بدم.
تو این روش چون هر مقاله با کل مقالات مقایسه میشه احساس میکنم روش کندی هستش.
مهندس جان شما راهکار سریع تری سراغ داری؟
ارائه راه حل کاربردی نیاز به بررسی بیشتر دارد اما اگر نتوانید از امکانات خود MySQL استفاده کنید و توابعی مانند similar_text با توجه به حجم محتوا کارایی لازم را نداشته باشند باید الگوریتم اختصاصی طراحی کنید، به فرض حداقل در تئوری چند بخش از هر مقاله را به صورت تصادفی انتخاب و با دیتابیس مقایسه کنید و البته برای حل مشکل سرعت، سیستم ایندکس گذاری داشته باشید (کلمات کلیدی هر مقاله به همراه تکرار را داشته باشید و فقط در مقالاتی جستجو کنید که کلمه کلیدی آن با کلمه کلیدی مقاله مورد نظر همسان باشد)، در کل با این اوصاف کار سخت و زمانبر خواهد شد.
more لطفا پیش از ارسال دیدگاه نکات زیر را مد نظر داشته باشید:
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.



 refresh
10 × 10
6 × 9
20 × 20
=