• Вопрос без рабочей ссылки на проблему считается риторическим. Без ссылки и скриншота - провокацией!
  • Темы озаглавленные с маленькой буквы или капсом удаляются без предупреждения!

Решено Сортировка по наличию

Image CMS
#1
Коллеги, нужна помощь, может кто-то уже сталкивался, но на форуме вроде не нашел эту тему. Как можно вывести товары по наличию, т.е. те которых нет в наличии выводить в самом конце? Искал пока ничего не нарыл кроме как того что вроде нужно хук цеплять на
woocommerce_get_catalog_ordering_args
 

searchingman

Гуру
Местный
#2
По материалам статьи от ADv, за что ему спасибо!
В functions.php своей темы вставляем код.
PHP:
add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args' );

function custom_woocommerce_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );

if ( 'stock_list_asc' == $orderby_value ) {
    $args['orderby'] = 'meta_value_num wp_posts.ID';
    $args['order'] = 'ASC';
    $args['meta_key'] = '_stock';
}
elseif ( 'stock_list_desc' == $orderby_value ) {
    $args['orderby'] = 'meta_value_num wp_posts.ID';
    $args['order'] = 'DESC';
    $args['meta_key'] = '_stock';
}

return $args;
}

add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby' );

function custom_woocommerce_catalog_orderby( $sortby ) {
$sortby['stock_list_desc'] = 'Остаток: по убыванию';
$sortby['stock_list_asc'] = 'Остаток: по возрастанию';
return $sortby;
}
В итоге не теме storefront выглядит так.
1. В админке появились 2 пункта сортировки. http://take.ms/vPPik
Можно выбрать нужный пункт по умолчанию.
2. В публичной части появились 2 новых пункта сортировки. http://take.ms/5ye1G
 
#3
searchingman, спасибо за помощь как всегда (y), но у меня оказалось проблема чуть в другом, понял это уже после того как написал тут. Но этот код очень кстати! Думаю многим будет полезен, еще раз спасибо!
 
#4
Вот еще интересный код вставляется в functions.php
PHP:
class iWC_Orderby_Stock_Status
{

    public function __construct()
    {
        // Check if WooCommerce is active
        if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
            add_filter('posts_clauses', array($this, 'order_by_stock_status'), 2000);
        }
    }

    public function order_by_stock_status($posts_clauses)
    {
        global $wpdb;
        // only change query on WooCommerce loops
        if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag())) {
            $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) ";
            $posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby'];
            $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
        }
        return $posts_clauses;
    }
}

new iWC_Orderby_Stock_Status;
 

cwolo4

Новичок
#5
PHP: add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args' );

function custom_woocommerce_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );

if ( 'stock_list_asc' == $orderby_value ) {
$args['orderby'] = 'meta_value_num wp_posts.ID';
$args['order'] = 'ASC';
$args['meta_key'] = '_stock';
}
elseif ( 'stock_list_desc' == $orderby_value ) {
$args['orderby'] = 'meta_value_num wp_posts.ID';
$args['order'] = 'DESC';
$args['meta_key'] = '_stock';
}

return $args;
}

add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_orderby' );
add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby' );

function custom_woocommerce_catalog_orderby( $sortby ) {
$sortby['stock_list_desc'] = 'Остаток: по убыванию';
$sortby['stock_list_asc'] = 'Остаток: по возрастанию';
return $sortby;
}
обьясните мне как это может работать?
$args['meta_key'] = '_stock'; ключа "_stock" не существует, тут скорее всего _stock_status
$args['orderby'] = 'meta_value_num wp_posts.ID'; в это вообще как?

а где запрос/фильтрация к таблице wp_postmeta, ведь в ней мы ведем учет статуса наличия товара
ниже что приведен код работает как сортировка по умолчанию, сначала тот товар, что есть в наличии, затем того что нет, но хотелось бы применить сортировку, по наличию, сначала те что есть, нажал на кнопку и сортировка вначале тех что нет
 

searchingman

Гуру
Местный
#6
$args['meta_key'] = '_stock'; ключа "_stock" не существует, ...
Нас рассудят исходники плагина.
Откройте файл \wp-content\plugins\woocommerce\includes\abstracts\abstract-wc-product.php (ссылка на GitHub)
* @property string $stock Stock amount
* @property string $stock_status Stock status
Код из того же файла из public function set_stock()
PHP:
// Update stock in DB directly
            switch ( $mode ) {
                case 'add' :
                    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = meta_value + %f WHERE post_id = %d AND meta_key='_stock'", $amount, $this->id ) );
                break;
                case 'subtract' :
                    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = meta_value - %f WHERE post_id = %d AND meta_key='_stock'", $amount, $this->id ) );
                break;
                default :
                    $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_value = %f WHERE post_id = %d AND meta_key='_stock'", $amount, $this->id ) );
                break;
            }
meta_key='_stock' !!!
 
Последнее редактирование:

cwolo4

Новичок
#7
ага и если мы не указали колличество то в итоге таблица будет

а надо сортировку по ключу _stock_status

тогда сортировка будет instock, потом по outofstock тогда количество не играет роли в сортировке.


первый же код сортировки не сортирует по наличию, основа его взята от сюда https://docs.woocommerce.com/document/custom-sorting-options-ascdesc/ ,
тут же указано что можно туда вносить https://codex.wordpress.org/Class_Reference/WP_Query#Order_.26_Orderby_Parameters
$args['orderby'] = 'meta_value_num';//поле по которому сортируем
$args['order'] = 'DESC';//по возрастанию (ASC) или убыванию (DESC)
$args['meta_key'] = '';//по конкретному совпадению ключа, нам бы не плохо было бы вставить _stock_status , но его то нет .
Помогите туда добавить данный запрос, что бы товар сортировался по статусу наличия, а не по его остатку на складе.
 
Последнее редактирование:

mulch

Форумчанин
#8
Вот еще интересный код вставляется в functions.php
PHP:
class iWC_Orderby_Stock_Status
{
    public function __construct()
    {
        // Check if WooCommerce is active
        if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
            add_filter('posts_clauses', array($this, 'order_by_stock_status'), 2000);
        }
    }

    public function order_by_stock_status($posts_clauses)
    {
        global $wpdb;
        // only change query on WooCommerce loops
        if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag())) {
            $posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) ";
            $posts_clauses['orderby'] = " istockstatus.meta_value ASC, " . $posts_clauses['orderby'];
            $posts_clauses['where'] = " AND istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' " . $posts_clauses['where'];
        }
        return $posts_clauses;
    }
}

new iWC_Orderby_Stock_Status;
Интересный код, но он блокирует отображение записей, т.к. записи - тоже посты, но без ключа "_stock_status". Жаль что SQL позабыл - сижу и не могу понять, чего добавить в $posts_clauses, чтобы записи тоже набивались в сортировку.
Буду благодарен за подсказку, коллеги.
 
#9
Интересный код, но он блокирует отображение записей, т.к. записи - тоже посты, но без ключа "_stock_status". Жаль что SQL позабыл - сижу и не могу понять, чего добавить в $posts_clauses, чтобы записи тоже набивались в сортировку.
Буду благодарен за подсказку, коллеги.
Не совсем ясна ваша проблема, в принципе этот код ни как не касатется записей вообще.
 

mulch

Форумчанин
#10
Да вот как раз из-за фильтра $posts_clauses[ и касается - http://wp-kama.ru/hook/posts_clauses
Отключаю - в виджете "Свежие записи" все есть. Включаю обратно - на страницах, где код работает (is_shop() || is_product_category() || is_product_tag()) - записей вообще нет.
Кстати добавил еще для сортировки страницу своих таксономий - || is_tax().
 

mulch

Форумчанин
#11
Вот наконец добрался до этого вопроса.
Изменил формовку SQL запроса (привожу группу строк):
....
if (is_woocommerce() && (is_shop() || is_product_category() || is_product_tag() || is_front_page() || is_tax())) {
$posts_clauses['join'] .= " INNER JOIN $wpdb->postmeta istockstatus ON ($wpdb->posts.ID = istockstatus.post_id) ";
$posts_clauses['where'] = " AND (istockstatus.meta_key = '_stock_status' AND istockstatus.meta_value <> '' AND $wpdb->posts.post_type = 'product') OR ($wpdb->posts.post_type = 'post' AND $wpdb->posts.post_status = 'publish' AND istockstatus.meta_key = '_edit_lock') " . $posts_clauses['where'];
$posts_clauses['orderby'] = " istockstatus.meta_value ASC, $wpdb->posts.post_date DESC, " . $posts_clauses['orderby'];
....
Теперь в сайдбаре в виджете "Свежие записи" записи есть, но от первых к последним! Да и вообще как я понял этот код не дает возможность дополнительной сортировки стандартным выпадающим списком WC. (по цене (уб/возр), по рейтингу, по популярности).
Хотя структура его формирования вроде как прибавляет в конец дополнительные значения.
А как вывести на экран полную строку $posts_clauses после ее формирования?
 
Сверху Снизу