بالاخره بعد مدتها وقت شد یه پست آموزشی آماده کنم. حتما براتون پیش اومده که یک کاری رو داخل حلقه با php دارید انجام میدید مثلا یک فانکشن خاصی روی تعداد 100 ایتم در یک حلقه اجرا میشه و میخواهید بعد از انجام عملیات روی هر ایتم به کاربر در فرانت اند نشون بدید الان ایتم فلان پراسس شده و اینقدر درصد از کل کار پیش رفته. خب چطوری میشه؟ اگر پیش نیومد براتون هم بخونید پست رو بعدا بدرد تون میخوره.
اول میاییم یک سناریو واقعی رو تعریف میکنیم و بعد برایش راه حل ها رو میگم و در نهایت سورس رو بصورت کامل قرار میدم.
درخواست: میخواهیم یک meta از پست های سایت رو تغییر بدیم، مثلا 1500 تا پست داریم. خب یه راه حل اینه که با wp_localize_script بیاییم لیست پست ها رو که از get_posts گرفتیم رو به فایل جاوا اسکریپت مون بدیم، بعد اون طرف با اجاکس و مثلا متد post ریکوئست بفرستیم پست ها رو یکی یکی داخل لوپ (یا با سینکرونوس) و بعد از اتمام هر ریکوئست نتیجه رو بگیریم نشون بدیم تو فرانت. ولی یکم پیچیده هست برای کار به این سادگی درسته؟ میخواهیم یه متا از پست ها رو تغییر بدیم که کلا با php میشه انجامش داد، دیگه جاوا اسکریپت و اینا چیه دست و پا گیر شده!
راه حل: قرار هست با افزودن یک کوئری به صفحه داشبورد مدیریت سایت، یک صفحه سفید باز بشه و پست ها رو یکی یکی پراسس کنه متا شون رو تغییر بده و همزمان هم درصد پیشرفت رو نشون بده، و کاربر هم بتونه وسط پروسه سیستم رو متوقف کنه. و برای پراگرس بار هم بکگراند بادی رو با گرادینت رنگ میکنیم.
کد زیر رو با توضیحات کامل هست :
/*
Plugin Name: Bulk Update Post meta
Version: 0.1
Plugin URI: https://amirhosseinhpv.ir/news/echo-on-loop-pure-php/
Description:
Author: Amirhosseinhpv
Author URI: https://hpv.im/
*/
/**
* check if we are receiving request in admin area
* e.g. https://yoursite.com/wp-admin/?bulk_update_post_meta
*/
if ( is_blog_admin() && isset($_GET["bulk_update_post_meta"])){
bulk_update_post_meta_proccess();
}
/**
* Bulk update post meta function
*/
function bulk_update_post_meta_proccess()
{
// first get all posts ids as array
$array_posts_ids = get_posts(
array(
"post_type" => "post",
"posts_per_page" => -1,
"fields" => "ids",
)
);
// declare variables
$i = 0;
$success_items = 0;
$current_progress = 0;
$total_posts = count($array_posts_ids);
// we are going to sent js to frontend as we want to update frontend dom elements
// so what happens here is if we have 12000 item, we will output js for 12000 times,
// which may cause browser crash, so we output js only for 300 times
$steps = floor($total_posts / 300);
// Implicit flushing will result in a flush operation after every output call,
// so that explicit calls to flush() will no longer be needed
ob_implicit_flush(true);
// turn output buffering on
ob_start();
// let user know we started process
echo "<h1>Updating Meta in progress, press ESC to cancel.</h1>";
foreach( $array_posts_ids as $post) {
// set current loop item position
$i++;
// get post meta
$views = get_post_meta( $post, "views", true);
// set post meta
$update = update_post_meta($post, "views", $views*7 );
if (true === $update){
$success_items++;
}
// calculate current progress percentage, output be like 48.78%
$_precent = min(100, 100 * $i / $total_posts);
$current_precent = sprintf("%'05.2f%%", );
// now output loop information
// output be like: 50.00% ~~ 500 / 1000 ~~ Post ID #7896 meta updated!
printf("<p>%s ~~ %02d / %02d ~~ Post ID #%s meta updated!</p>", $current_precent, $i, $total_posts, $post);
// we only update progressbar or page title precentage 300 times, no matter how many items are in loop
if ($i % $steps == 0 ){
echo "<script>
/* update page title */
document.title = 'Updating $current_precent';
/* make a large progressbar with body background */
document.querySelector('body').style.backgroundImage = 'linear-gradient(to right, rgba(0, 223, 56, 0.18) {$_precent}%, white {$_precent}%)';
/* scroll to bottom */
window.scrollTo(0, document.body.scrollHeight);
</script>";
}
ob_end_flush();
ob_flush();
flush();
ob_start();
}
echo "<h1><strong>$success_items</strong> items of total <strong>$total_posts</strong> posts meta updated successfully.</h1>";
ob_end_flush();
exit;
}
کد زیر هم بدون کامنت و جمع جور شده است.
/*
Plugin Name: Bulk Update Post meta
Version: 0.1
Plugin URI: https://amirhosseinhpv.ir/news/echo-on-loop-pure-php/
Description:
Author: Amirhosseinhpv
Author URI: https://hpv.im/
*/
/* usage: https://yoursite.com/wp-admin/?bulk_update_post_meta */
if ( is_blog_admin() && isset($_GET["bulk_update_post_meta"])){
$array_posts_ids = get_posts( array( "post_type" => "post", "posts_per_page" => -1, "fields" => "ids", ) );
$i = 0; $success_items = 0; $current_progress = 0; $total_posts = count($array_posts_ids);
$steps = floor($total_posts / 300);
ob_implicit_flush(true); ob_start();
echo "<h1>Updating Meta in progress, press ESC to cancel.</h1>";
foreach( $array_posts_ids as $post) {
$i++;
$views = get_post_meta( $post, "views", true);
$update = update_post_meta($post, "views", $views*7 );
if (true === $update){ $success_items++; }
$_precent = min(100, 100 * $i / $total_posts);
$current_precent = sprintf("%'05.2f%%", );
printf("<p>%s ~~ %02d / %02d ~~ Post ID #%s meta updated!</p>", $current_precent, $i, $total_posts, $post);
if ($i % $steps == 0 ){
echo "<script>document.title = 'Updating $current_precent';
document.querySelector('body').style.backgroundImage = 'linear-gradient(to right, rgba(0, 223, 56, 0.18) {$_precent}%, white {$_precent}%)';
window.scrollTo(0, document.body.scrollHeight);</script>";
}
ob_end_flush(); ob_flush(); flush(); ob_start();
}
echo "<h1><strong>$success_items</strong> items of total <strong>$total_posts</strong> posts meta updated successfully.</h1>";
ob_end_flush(); exit;
}
از این ترفند برای نمایش درصد آپلود هم میشه استفاده کرد، همونطور که در اسکریپت Upload File from URL to WebServer از این روش استفاده کردم برای زمانی که فایل از URL در سرور آپلود میشه درصد رو نشون میده و پراگرس هم با رنگ بادی مشخص میشه.
برای دمو فیلم زیر رو ببینید:
2 دیدگاه. همین الان خارج شوید
مهندس جان واقعا عالی بود از مطالعه این پست واقعا لذت بردم ، ممنون از زمانی که گذاشتید 💙
ممنونم از لطف تون مهندس جان 🧡