Jump to content

Групповое добавление дополнительных категорий к товарам


Recommended Posts

Данная доработка позволяет производить групповое добавление (или удаление) дополнительных категорий к выбранным товарам, с помощью селекта внизу страницы товаров.

7a2e06078f864b25a41b0a3c48dcec85.png

 

 

 

1. В файле /simpla/design/html/products.tpl после строк:

{if $categories|count>1}
<option value="move_to_category">Переместить в категорию</option>
{/if}

Добавить:

{if $categories|count>1}
<option value="move_to_additional">Дополнительные категории</option>
{/if}

 

 

 

2. В том же файле, после строк:

<span id="move_to_category">
<select name="target_category">
    {function name=category_select level=0}
    {foreach $categories as $category}
        <option value='{$category->id}'>{section sp $level}    {/section}{$category->name|escape}</option>
        {category_select categories=$category->subcategories selected_id=$selected_id level=$level+1}
    {/foreach}
    {/function}
    {category_select categories=$categories}
</select>
</span>

Добавить:

<span id="move_to_additional">
<select name="target_additional">
    <option value="0">Удалить все доп. категории</option>
    {function name=additional_select level=0}
    {foreach $categories as $category}
        <option value='{$category->id}'>{section sp $level}    {/section}{$category->name|escape}</option>
        {additional_select categories=$category->subcategories selected_id=$selected_id level=$level+1}
    {/foreach}
    {/function}
    {additional_select categories=$categories}
</select>
</span>

 

 

 

3. В том же файле, после строк:

    // Перенос товара в другую категорию
    $("#action select[name=action]").change(function() {
        if($(this).val() == 'move_to_category')
            $("span#move_to_category").show();
        else
            $("span#move_to_category").hide();
    });
    $("#right_menu .droppable.category").droppable({
        activeClass: "drop_active",
        hoverClass: "drop_hover",
        tolerance: "pointer",
        drop: function(event, ui){
            $(ui.helper).find('input[type="checkbox"][name*="check"]').attr('checked', true);
            $(ui.draggable).closest("form").find('select[name="action"] option[value=move_to_category]').attr("selected", "selected");    
            $(ui.draggable).closest("form").find('select[name=target_category] option[value='+$(this).attr('category_id')+']').attr("selected", "selected");
            $(ui.draggable).closest("form").submit();
            return false;            
        }
    });

Добавить:

    // Добавление товару дополнительной категории
    $("#action select[name=action]").change(function() {
        if($(this).val() == 'move_to_additional')
            $("span#move_to_additional").show();
        else
            $("span#move_to_additional").hide();
    });
    $("#right_menu .droppable.category").droppable({
        activeClass: "drop_active",
        hoverClass: "drop_hover",
        tolerance: "pointer",
        drop: function(event, ui){
            $(ui.helper).find('input[type="checkbox"][name*="check"]').attr('checked', true);
            $(ui.draggable).closest("form").find('select[name="action"] option[value=move_to_additional]').attr("selected", "selected");    
            $(ui.draggable).closest("form").find('select[name=target_additional] option[value='+$(this).attr('category_id')+']').attr("selected", "selected");
            $(ui.draggable).closest("form").submit();
            return false;            
        }
    });

 

 

 

4. В файле /simpla/design/css/style.css заменить строки:

div#action span#move_to_page, div#action span#move_to_category, div#action span#move_to_brand{
    display:none;
}

На строки:

div#action span#move_to_page, div#action span#move_to_category, div#action span#move_to_additional, div#action span#move_to_brand{
    display:none;
}

 

 

 

5. В файле /simpla/ProductsAdmin.php после строк:

case 'move_to_category':
{
    $category_id = $this->request->post('target_category', 'integer');
    $filter['page'] = 1;
    $category = $this->categories->get_category($category_id);
    $filter['category_id'] = $category->children;
         
    foreach($ids as $id)
    {
        $query = $this->db->placehold("DELETE FROM __products_categories WHERE category_id=? AND product_id=? LIMIT 1", $category_id, $id);    
        $this->db->query($query);                      
        $query = $this->db->placehold("UPDATE IGNORE __products_categories set category_id=? WHERE product_id=? ORDER BY position DESC LIMIT 1", $category_id, $id);    
        $this->db->query($query);
        if($this->db->affected_rows() == 0)
            $query = $this->db->query("INSERT IGNORE INTO __products_categories set category_id=?, product_id=?", $category_id, $id);    

    }
    break;
}

Добавить:

case 'move_to_additional':
{
    $additional_id = $this->request->post('target_additional', 'integer');
    $filter['page'] = 1;
    $category = $this->categories->get_category($additional_id);
    $filter['category_id'] = $category->children;
                 
    foreach($ids as $id)
    {
        if($additional_id == 0)
        {
            $query = $this->db->placehold("DELETE FROM __products_categories WHERE product_id=? AND position<>0", $id);    
            $this->db->query($query);
        }                  
        else
        {
            $query = $this->db->placehold("SELECT count(*) as count FROM __products_categories WHERE product_id=?", $id);
            $this->db->query($query);
            $count = $this->db->result('count');
            $query = $this->db->query("INSERT IGNORE INTO __products_categories set category_id=?, product_id=?, position=?", $additional_id, $id, $count);
        }
                         

    }
    break;
} 

 

Link to post
Share on other sites

Молодец что написал статью!

Как будет сохраняться порядок категорий у каждого товара?

 

Посмотрите внимательно:

$query = $this->db->placehold("SELECT count(*) as count FROM __products_categories WHERE product_id=?", $id);
$this->db->query($query);
$count = $this->db->result('count');
$query = $this->db->query("INSERT IGNORE INTO __products_categories set category_id=?, product_id=?, position=?", $additional_id, $id, $count);
Edited by parampados
Link to post
Share on other sites

Посмотрите внимательно:

$query = $this->db->placehold("SELECT count(*) as count FROM __products_categories WHERE product_id=?", $id);
$this->db->query($query);
$count = $this->db->result('count');
$query = $this->db->query("INSERT IGNORE INTO __products_categories set category_id=?, product_id=?, position=?", $additional_id, $id, $count);

 

 

Если посмотреть на этот код внимательно, то легко обнаружить, что вставляемая категория далеко не всегда будет последней в списке...
Link to post
Share on other sites

Если посмотреть на этот код внимательно, то легко обнаружить, что вставляемая категория далеко не всегда будет последней в списке...

Ну вот и я о чем)
Link to post
Share on other sites

А если более развёрнуто, то:

Кейс работает для каждой отдельной связки «товар» + «категория» и в данном случае count всегда будет равен текущему количеству категорий у товара.

В тоже время, возможности сортировать доп. категории вручную возможности нет, т.е. position добовляемой доп. категории всегда будет равен count.

Проверьте.

Edited by parampados
Link to post
Share on other sites

count покажет количество, но position одной из категорий может быть больше количества этих самых категорий, и как следствие категория попадет в "середину списка" категорий товара.

тут актуальнее использовать максимальное значение position+1

Link to post
Share on other sites

В тоже время, возможности сортировать доп. категории вручную возможности нет

 

Это правильно.

 

т.е. position добовляемой доп. категории всегда будет равен count.

 

А здесь целых две ошибки: неверно как основное утверждение, так и связка "т.е.".

 

Проверьте.

 

Для того, чтобы проверить правильность Вашего утверждения, надо проверять ВСЕ ВОЗМОЖНЫЕ варианты работы в админке. Это невозможно В ПРИНЦИПЕ.

 

А вот для того, чтобы проверить НЕправильность Вашего утверждения, достаточно всего лишь привести пример. И если не зацикливаться на Вашем коде, а помнить, что в админке есть и еще довольно много действий, то привести нужный пример будет уже проще...

 

Если настаиваете на своем очевидно неправильном тезисе, готов поспорить, например на 1000$.

Я утверждаю, что Ваш метод при штатной работе в админке в некоторых ситуациях может вставлять категорию НЕ в конец списка...

Link to post
Share on other sites

А я утверждаю что почти каждое Ваше решение имеет изъяны.

Хватит разводить лирику.

Либо комментируем по существу (с указанием на точное место ошибки, и методами борьбы с ними), либо не комментируем вообще.

Link to post
Share on other sites

Kors, весь смысл Вашего сообщения, сводится к тому, что если бы у бабушки были яйца, она была бы дедушкой.

Существует правило хорошего тона: «критикуешь – предлагай».

 

Sheeft, дело в том, что count() считает с единицы, а position объявляется с нуля.

Таким образом, в случае если доп.категории удаляются «стандартно» со страницы товара или с помощью предлагаемой мной «Удалить все доп.категории», count будет равен следующей position для конкретной связки «товар»+«категория».

Обратите внимание, что при удалении/добавлении доп.категорий со страницы товара, position связок «товар»+«категории» всегда обновляется и начинается с нуля.

Link to post
Share on other sites

Вы проверяли работу предлагаемой доработки?

Будьте добры, конкретный пример того, что работает неправильно.

 

Сначала маленькое отступление. Многие таблицы БД имеют поле ID первичного ключа.

При создании новых записей значения ID генерируются автоматически по порядку.

Например, если в начале работы таблица пусть и админ создает 5 объектов, то они получают ID=1,2,3,4,5.

Если потом удалить пару объектов, то ряд ID будет иметь более сложную структуру, например ID=1,4,5.

Все это азбука, которую обычно знают даже начинающие пользователи, которые не ленятся заглядывать иногда в базу.

Тем более это прекрасно знают программисты.

 

А теперь вернемся к нашим баранам. Поле position в таблице s_products_categories, хоть и не является ключевым, но ведет себя подобным образом.

Например, если в админке на странице товара указать товару 5 категорий, то для этого товара в таблице появятся 5 записей со значениями поля position=0,1,2,3,4.

А теперь, если удалить парочку из этих 5 категорий, то в таблице останутся только 3 записи, например, со значениями поля position=0,1,4.

Теперь добавим к товару новую категорию, применив предлагаемый метод. Имеем count = 3, поэтому появится добавочная запись со значением position=3.

В итоге - новая запись в порядке категорий встала не в конце списка, а в серединке.

 

Думаю, примерно такое имели в виду, кроме меня, также и Noxter в #5 и Sheeft в #8.

Три однотипных замечания от фрилансеров - стоило бы задуматься, а не лезть в бутылку...

 

Если применить предложение Sheeft-а

тут актуальнее использовать максимальное значение position+1

то это исправит описанную ошибку. Но останется другая. Думаю, будет интереснее Вам самому, если найдете ее сами...

 

Хватит разводить лирику.

Либо комментируем по существу...

 

Надеюсь, Вам понравится мой подробный комментарий по существу и с деталями...

 

А я утверждаю что почти каждое Ваше решение имеет изъяны.

 

Может, Вы окажете мне ответную любезность, и прокомментируете свое утверждение развернуто и доказательно?

Меня очень интересует методика получения подобных выводов.

Если бы меня попросили оценить процент решений с изъянами или без изъянов от какого-либо работающего фрилансера, я бы сказал, что это задача необъятная:

1. надо иметь список решений с подробностями,

2. надо каждое или хотя бы большинство тестировать,

3. Если решение платное, надо еще потратиться.

В итоге, по моим прикидкам, чтобы высказывать такое с полной уверенностью и ответственностью, надо потратить рабочего времени уйму. Возможно, месяцы. Скорее всего, даже больше, чем на создание CMS с нуля. И денег немало...

4. А за время тестирования появятся новые решения или частично исправятся ошибки в существующих - для актуальности надо опять заново тестировать...

 

Edited by Kors
Link to post
Share on other sites

 

А теперь вернемся к нашим баранам. Поле position в таблице s_products_categories, хоть и не является ключевым, но ведет себя подобным образом.
Например, если в админке на странице товара указать товару 5 категорий, то для этого товара в таблице появятся 5 записей со значениями поля position=0,1,2,3,4.

 

Всё верно.

 

 

А теперь, если удалить парочку из этих 5 категорий, то в таблице останутся только 3 записи, например, со значениями поля position=0,1,4.

 

Я уже писал, что если доп. категории удаляются «стандартно» через админку со страницы товара, то в таблице останутся записи со значениями поля position=0,1,2, т.к. при удалении/добавлении доп. категорий, position связок «товар»+«категории» всегда обновляется и начинается с нуля. 

 

Я абсолютно согласен, что при удалении полей из таблицы вручную, проявится описанное вами поведение, но безоглядным удалением полей из БД можно всё что угодно сломать.

Таким образом, предлагаемое мной решение будет полностью работоспособным, в случае если доп. категории добавляются/удаляются через админку (как это делает большинство пользователей).

 

 

тут актуальнее использовать максимальное значение position+1

 

Можно, но всё прекрасно работает и без этого.

 

P.S.: Ну и напоследок у меня вопрос, для чего вам нужен порядок сортировки дополнительных категорий товара? Важна главная категория с position=0, а какое значение имеет порядок дополнительных?

 

 

 

Link to post
Share on other sites

Таким образом, предлагаемое мной решение будет полностью работоспособным, в случае если доп. категории добавляются/удаляются через админку (как это делает большинство пользователей)

 

Видимо, я недостаточно подробно объяснил, дополняю.

Проводим следующие действия (все штатно в админке + обсуждаемая доработка):

1. В админке на странице товара укажем товару 5 категорий, тогда при сохрании для этого товара в таблице появятся 5 записей со значениями поля position=0,1,2,3,4.

2. В админке на странице КАТЕГОРИЙ удалим парочку из этих 5 категорий (удалим не дополнительные категории у товара, а удалим категории вообще). В таблице останутся только 3 записи, например, со значениями поля position=0,1,4.

3. Теперь добавим к товару новую категорию, применив предлагаемый метод. Имеем count = 3, поэтому появится добавочная запись со значением position=3.

4. В итоге - новая запись в порядке категорий встала не в конце списка, а в серединке.

 

P.S.: Ну и напоследок у меня вопрос, для чего вам нужен порядок сортировки дополнительных категорий товара? Важна главная категория с position=0, а какое значение имеет порядок дополнительных?

 

Это уже другой вопрос. Большей частью этот порядок действительно не нужен. Нужно реально только разделение на основную категорию и дополнительные.

Основная категория участвует, например, в хлебных крошках, для SEO это обычно очень важно.

Поскольку уж речь зашла об этом, отмечу, что Ваша доработка при некоторых обстоятельствах может ПОРТИТЬ соотношение - основная категории и дополнительные категории. А по смыслу - не должно такого быть. Возникает уже некоторый риск проблем для SEO. Насколько я знаю, SEO-спецы такое очень не любят - менять основную категорию без веских причин...

Link to post
Share on other sites

А нет, все. Разобрался. Нужно выбрать сначала "Доп.категории в первом селекте", а потом нажать "Применить". Вопрос снят

Link to post
Share on other sites

Обнаружился еще такой маленький момент:

если импортировать новый товар с несколькими категориями, а потом попробовать удалить доп категории предлагаемой доработкой, то это работать не  будет. Связано это с тем, что автор считает position=0 признаком основной категории, а это не всегда верно...

 

В связи с этим предложение автору:

полезно было бы сделать удаление не СРАЗУ ВСЕХ доп категорий, а одной указанной.

Ведь поскольку сделано добавление категорий, естественно сделать и обратную операцию удаления...

Link to post
Share on other sites
  • 3 years later...

Если посмотреть на этот код внимательно, то легко обнаружить, что вставляемая категория далеко не всегда будет последней в списке...

 

Можете пожалуйста помочь исправить данный код, чтобы категория была последней?

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...