Предположим, что есть товары, цена которых у продавца в долларах, но при этом на сайте мы хотим продавать эти товары за рубли по сегодняшнему курсу, чтобы не усложнять функционал мультивалютностью.
Получаем актуальный курс валюты
function get_currency_cb($code_valute = 'USD', $time_cash = '60' ) {
if ($code_valute != 'USD' && $code_valute != 'EUR') $code_valute = 'USD';
if ($time_cash <= 0) $time_cash = 60; // время кеширования в минутах
$name_cash = 'cash_kurs_cb';
$cached = get_transient($name_cash);
if ($cached !== false && $cached['code'] == $code_valute) {
$kurs_cb = $cached;
return $kurs_cb;
}
else {
libxml_use_internal_errors(true);
$kurs_cb_xml = simplexml_load_file("http://www.cbr.ru/scripts/XML_daily.asp");
if ($kurs_cb_xml === false) {
echo "Ошибка загрузки XML\n";
foreach(libxml_get_errors() as $error) {
echo "\t", $error->message;
}
$kurs_cb = $cached;
return $kurs_cb;
} else {
foreach ($kurs_cb_xml->Valute as $valute) {
if ((string)$valute->CharCode == $code_valute) {
$kurs_cb['date'] = (string)$kurs_cb_xml['Date'];
$kurs_cb['kurs'] = (string)$valute->Value;
$kurs_cb['code'] = $code_valute;
break;
}
}
$kurs_cb['kurs'] = round(str_replace(',','.',$kurs_cb['kurs']),2);
set_transient($name_cash, $kurs_cb, MINUTE_IN_SECONDS * $time_cash);
return $kurs_cb;
}
}
}
Заводим поле Валюта
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields() {
global $woocommerce, $post;
$kurs_cb = get_currency_cb('USD');
$cinfo = 'Курс доллара на '.$kurs_cb['date'].' — '.$kurs_cb['kurs'].' руб.';
echo '<div class="options_group">';
woocommerce_wp_text_input(
array(
'id' => '_shop_currency',
'label' => __( 'Цена в долларах ($)', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => $cinfo
)
);
echo '</div>';
}
function woo_add_custom_general_fields_save( $post_id ){
$woocommerce_shop_currency = $_POST['_shop_currency'];
if( !empty( $woocommerce_shop_currency ) ) update_post_meta( $post_id, '_shop_currency', esc_attr( $woocommerce_shop_currency ) );
else delete_post_meta( $post_id, '_shop_currency', esc_attr( $woocommerce_shop_currency ) );
}
Обновляем поле Цена (в рублях)
При создании или обновлении товара, если заполнено поле Валюта, то происходит расчет стоимости товара в рублях по курсу и обновляет стандартное поле цена.
// Обновляем цену в рублях при заполненном поле валюта
// Работает как при создании нового товара, так и при обновлении
add_action( 'woocommerce_update_product', 'mp_sync_on_product_save', 10, 1 );
function mp_sync_on_product_save($post_id) {
$woocommerce_shop_currency = $_POST['_shop_currency'];
if ( !empty($woocommerce_shop_currency) ) {
$kurs_cb = get_currency_cb('USD');
//$kurs = '64';
$newprice = round($woocommerce_shop_currency * $kurs_cb['kurs']);
update_post_meta($post_id, '_regular_price', $newprice);
update_post_meta($post->ID, '_price', $newprice);
}
}
Ежедневное обновление цен
Естественно не удобно было бы обходить ежедневно все товары, чтобы обновить стоимость (в связи с изменением курса), поэтому создаем функцию обновляющую все позиции с валютой. Создаем шаблон страницы:
<?php global $post;
$args = array(
'posts_per_page' => -1,
'post_type' => 'product'
);
$myposts = get_posts( $args );
foreach( $myposts as $post ) : setup_postdata($post);
$woocommerce_shop_currency = get_post_meta($post->ID, '_shop_currency', true);
if(!empty($woocommerce_shop_currency)){
$kurs_cb = get_currency_cb('USD');
//$kurs = '64';
$newprice = round($woocommerce_shop_currency * $kurs_cb['kurs']);
update_post_meta($post->ID, '_regular_price', $newprice);
update_post_meta($post->ID, '_price', $newprice);
echo '<h3>'.$post->post_title.'</h3>';
}
endforeach; wp_reset_postdata(); ?>
Получившийся URL страницы добавляем в CRON (1-2 раза в сутки).
Добрый день!
Стоимость рассчитывает правильно и в карточке товара все правильно
Но в разделе товары, стоимость не меняетсяКак ее изменить
Добрый день!
Цена обновляется в базе данных. Она должна обновляться во всех шаблонах.
Добрый день!Alexandr, у меня не получается последний этап
Ежедневное обновление цен
Видимо я что-то не так делаюЯ данный код добавлял в WP CronПодскажите, пожалуйста, как правильно сделать последний этап Ежедневное обновление цен, чтобы все работало
Как обновить цену в шаблонах?!
Добрый день! Если Вы все настроили верно, и при переходе по определенному url (с соответствующим шаблон с функцией обновления) цены обновляются, то нужно установить этот url на CRON. Как нибудь опишу подробный процесс, но сейчас Вам проще обратится в тех. поддержку хостинга — они подскажут быстрее. Если вопрос по созданию шаблона то можете почитать тут.
Alexandr, спасибо, что отвечаете и оказываете посильную помощь
Я правильно понимаю, что я должен создать файл с кодом Ежедневное обновление цен
Далее разместить страницу в корне своей темы? Или где?
И при открытии страницы, цены должны обновляться, верно? Так можно протестировать!
Далее необходимо прописать в cron, я пытался это сделать при помощи wp cron, но ничего не вышло…
На текущий момент, я так понимаю, что мне нужно правильно создать страницу Ежедневное обновление цен
Создаю php с кодом Ежедневное обновление ценФайл размещаю в корне темыОткрываю его, цены должны изменитьсяДалее в cron на хостинг, все верно?
Или я что-то делаю не так?!
Создал страницу
Закинул в корень сайтаВыполнилТакая ошибкаНеустранимая ошибка: вызов неопределенной функции get_posts() в файле /var / www / u0081537/ec-spa. ru / page_kurs_cena. php:8 Трассировка стека: #0 {главная} вброшено /var/www/u0081537/ec-spa.ru/page_kurs_cena.php на линии 8
Мне подсказали что ошибка может быть в том, код по каким-то причинам не имеет доступ к функции get_post(), возможно не в том месте он вызывается или не подключились нужные библиотеки
Если этот файл запускается сам по себе, а не внутри темы, то наверное окружение нужно подключать также, как в корневом файле index.php, только изменив путь на нужный.
/** Loads the WordPress Environment and Template */
require DIR . ‘/wp-blog-header.php’;
Либо, как второй вариант, можно подключить таким же образом файл wp-load.php из корня. И раз уж этот ваш скрипт не зависит от темы, то её нужно отключить. То есть получится как-то так:
<?php define( ‘WP_USE_THEMES’, false );require( ‘./wp-load.php’ );
В итоге код дорабали
<html>
<head>
<title>Updating prices on the site</title>
</head>
<body>
<p>Prices should change</p>
<?php
define( ‘WP_USE_THEMES’, false );
require( ‘./wp-load.php’ );
global $post;
$args = array(‘posts_per_page’ => -1, ‘post_type’ => ‘product’);
$myposts = get_posts( $args );
foreach( $myposts as $post ) : setup_postdata($post);
$woocommerce_shop_currency = get_post_meta($post_id, ‘_shop_currency’, true);
if ( !empty($woocommerce_shop_currency) ) {
$kurs_cb = get_currency_cb(‘EUR’);
//$kurs = ’77’;
$newprice = round($woocommerce_shop_currency * $kurs_cb[‘kurs’]);
update_post_meta( $post_id, ‘_regular_price’, $newprice );
update_post_meta( $post_id, ‘_price’, $newprice );
wc_delete_product_transients( $post_id ); // Update product cache
}
echo ‘<h3>’.$post->post_title.'</h3>’;
endforeach; wp_reset_postdata(); ?>
<p>And again the page code</p>
</body>
</html>
И после выполнения файла открывается страница с перечнем товаровВот ссылка https://ec-spa.ru/getkurs_v2.php
Повторюсь все описанное выше работает, курс в WP обновляется, но при открытии файла, ничего не происходит.
Очень надеюсь, что вы подскажете где я ошибсяЧто нужно изменитьИ сделать так, чтобы заработало
Если базовая цена обновляется в админке, а в карточке товара остается прежней, обратите внимание на мое решение:А в целом, хороший скрипт, спасибо 🙂
update_post_meta($post_id, '_regular_price', $newprice);
$post->ID» на «$post_id»update_post_meta($post_id, '_price', $newprice); // В этой строке я исправила "
Спасибо и Вам за ценное дополнение.
А можете поподробнее описать, куда эти куски кода вставлять ? Прям все в function.php друг за другом ?
Здравствуйте. Подскажите, пожалуйста, а как быть с импортом товаров с указанием цены по курсу? Я экспортировал товары, поменял произвольное поле (_shop_currency) с ценой по курсу и импортировал обратно, но базовая цена при этом осталась прежней. Приходится заходить в карточку товара и жать кнопку обновить чтобы базовая цена обновилась.
Как то можно это учесть, чтобы при импорте товаров базовая цена обновлялась с учетом указанной цены в валюте?