Warning: Creating default object from empty value in /home/p358670/www/old.didgo.ru/components/com_sh404sef/shInit.php on line 37
Дополнительные параметры (свойства) товара Virtuemart | Доработка Virtuemart
 


ВНИМАНИЕ!!! ЭТО СТАРАЯ ВЕРСИЯ САЙТА.

ДЛЯ ПОЛУЧЕНИЯ АКТУАЛЬНОЙ ИНФОРМАЦИИ

ПЕРЕЙДИТЕ НА WWW.DIDGO.RU




Опубликовано в: Доработка Virtuemart
18 сентября 2011


Дополнительные параметры (свойства) товара Virtuemart

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

Ну, я клиенту, мол, в Virte есть такой функционал. Когда добавляем товар, можно перейти на вкладочку "Габариты и вес" и указать требуемые параметры. "Э-э-э, нет" - сказал мне клиент. "Там можно указать только жёстко заданные параметры, а что если мне нужно указать материал, из которого сделано то или иное изделие?.."

Ну я, не будь дураком, предложил добавить требуемые поля в админку, также "жёстко", но клиент привёл железный аргумент. "А если," - говорит он - "я завтра захочу добавить ещё один параметр? А если вдруг какой-то станет ненужным вообще? Я может вообще завтра поменяю перечень товаров и начну продавать утиное перо. Нафига мне нужна тогда длина?"

Как, говорится, хозяин - барин. Надо - значит сделаем. Вирт установлен, чай заварен и налит, можно приступать к работе. Тем более, вчера мне привезли из Казахстана шаманские тапки Хоттабыча, вот такие:

Тапки Хоттабыча 1 Тапки Хоттабыча 2

Не оказалось под рукой фотоаппарата, поэтому щёлнул на свой древний телефон. Ну да не суть, в таких тапках работа пойдёт споро, даже бубен не потребуется. ))

Если у кого-то появятся критические замечания, предложения по улучшению кода - рад буду выслушать, принять во внимание и применить.

Теоретически всё это безобразие я видел так:

Страница параметров Страница добавления параметров к товару

Страница создания и редактирования параметров

Страница добавления параметров для товара

 

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

По структуре таблицы я решил сделать так:

Первая таблица будет содержать поля для ввода id параметра, его имени. Вторая таблица будет содержать id товара, id параметра, значение параметра. Ну что-то типа такого:

Таблица БД для дополнительных параметров товара

С первой таблицей всё понятно, во второй же я сейчас схематически показал, что для товара с id = 135 заданы три параметра: вес (id = 1), высота (id = 2), материал (id = 3) с соответствующими значениями.

Хотел бы остановиться на том, что данный материал я писал в процессе разработки функционала и первая таблица на самом деле будет иной. Изначально в первой таблице я планировал сделать только два столбца, но но в последствии решил добавить ещё два, один из которых будет хранить метку, опубликован параметр или нет, а второй будет отвечать за сортировку, чтобы клиент мог выводить параметры в той последовательности, в которой ему необходимо.

Сначала нужно решить первый пункт задачи. Т.е. сделать функционал добавления параметров. При этом, повторюсь, нужно предусмотреть возможность выключения, удаления, редактирования и сортировки.

 

ЧАСТЬ ПЕРВАЯ. Реализация функционала добавления параметров, создание списка параметров.


Шаг 1. Добавляем в БД таблицу 1.

Выполняем запрос в БД. Не забываем указывать вместо jos свой префикс.

CREATE  TABLE  `jos_vm_product_param` (
`param_id` INT( 11  )  AUTO_INCREMENT ,
 `param_name` VARCHAR( 64  )  CHARACTER  SET utf8 COLLATE utf8_general_ci,
 `param_publish` CHAR( 1  )  CHARACTER  SET utf8 COLLATE utf8_general_ci DEFAULT  'Y',
 `param_list_order` INT( 11  ) ,
 PRIMARY  KEY (  `param_id`  )
);

 

Шаг 2. Добавляем ссылку в меню админки Virtuemart.

Редактируем файл /administrator/components/com_virtuemart/header.php

В районе 283 строки, после кода:

 <li class="item-smenu vmicon vmicon-16-media">
 <a href="/<?php $sess->purl($_SERVER['PHP_SELF'] . "?pshop_mode=admin&page=product.file_form&product_id=$recent_product_id"); ?>"><?php echo $VM_LANG->_('PHPSHOP_FILEMANAGER_ADD') ?></a>
 </li>

Добавляем пункт меню:

<li class="item-smenu vmicon vmicon-16-content">
<a href="/<?php $sess->purl($_SERVER['PHP_SELF']."?pshop_mode=admin&page=product.product_param_list") ?>"><?php echo $VM_LANG->_('PHPSHOP_PRODUCT_PARAM_LIST_LBL') ?></a>
<hr />
</li>

Редактируем языковой файл /administrator/components/com_virtuemart/languages/common/russian.php

Вставляем в любое место страницы (я вставил после 432 строки) код:

'PHPSHOP_PRODUCT_PARAM_LIST_LBL' => 'Список параметров товара',
 'PHPSHOP_PRODUCT_PARAM_LIST_LBL_NAME' => 'Название параметра',
 'PHPSHOP_PRODUCT_PARAM_ADDEDIT' => 'Добавить/редактировать параметр',
 'PHPSHOP_PRODUCT_PARAM_NAME' => 'Введите название параметра',
 'VM_PRODUCT_PARAM_ERR_NAME' => 'Вы должны ввести название параметра',
 'VM_PRODUCT_PARAM_ERR_DELETE' => 'Пожалуйста, выберите параметр для удаления.',
 'VM_PRODUCT_PARAM_ADDED' => 'Новый параметр был успешно добавлен.',
 'VM_PRODUCT_PARAM_UPDATED' => 'Параметр успешно обновлён.',

Обновляем страницу вирта в админке. Должны увидеть нашу ссылку.

Результат добавления ссылки в админке Вирта

 

Шаг 3. Правим файлы.

Открываем файл /administrator/components/com_virtuemart/toolbar.php. После 80 строки:

'product.product_discount_list' => 'discountDelete',

вставляем код:

'product.product_param_list' => 'paramDelete',

Открываем файл /administrator/components/com_virtuemart/toolbar.virtuemart.php. После 74 строки:

"product.product_discount_list" => "discountDelete",

вставляем код:

"product.product_param_list" => "paramDelete",

 

Шаг 4. Добавляем новые файлы.

Сначала хотел расписать код, но тогда получится не статья, а длинная портянка. Поэтому я прилагаю данные файлы архивом.

Cкачиваете архив, распаковываете. Внутри будет папка administrator, копируете её в корень сайта, при этом добавляются новые, необходимые для работы файлы, а именно: ps_product_param.php, product.product_param_list.php и product.product_param_form.php.

 

Шаг 5. Прописываем функции.

В админке переходим: Компоненты -> Virtuemart -> Настройки -> Список модулей, напротив модуля Product кликаем на Список функций.

Страница со списком функций

 

После того, как перешли на страницу функций кликаем на кнопку Новый вверху и прописываем следующие значения:

Имя функции: paramAdd

Имя класса: ps_product_param

Метод класса: add

Права на функцию: storeadmin, admin

Описание: Добавление параметра

Сохраняем параметр и добавляем новый.

Имя функции: paramDelete

Имя класса: ps_product_param

Метод класса: delete

Права на функцию: storeadmin, admin

Описание: Удаление параметра

Сохраняем параметр и добавляем новый.

Имя функции: paramUpdate

Имя класса: ps_product_param

Метод класса: update

Права на функцию: storeadmin, admin

Описание: Обновление параметра

Сохраняем параметр и добавляем новый.

Имя функции: paramReorder

Имя класса: ps_product_param

Метод класса: reorder

Права на функцию: storeadmin, admin

Описание: Сортировка параметров

Всё, первая часть задачи завершена. Проверяем работу функционала.

 

ЧАСТЬ ВТОРАЯ. Добавляем параметры в товар.


Шаг 1. Добавляем новую вкладку.

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

Открываем файл /administrator/components/com_virtuemart/languages/product/russian.php. В любое место вставляем код:

'PHPSHOP_PRODUCT_FORM_PRODUCT_PARAM_LBL' => 'Параметры',

Я вставлял после 36 сроки.

Далее открываем файл /administrator/components/com_virtuemart/html/product.product_form.php.

После 100 строки:

$display_label = $VM_LANG->_('PHPSHOP_PRODUCT_FORM_ITEM_DISPLAY_LBL');

Вставляем код:

$dim_param_label = $VM_LANG->_('PHPSHOP_PRODUCT_FORM_PRODUCT_PARAM_LBL');

После 373-375 строк:

<?php
 editorArea( 'editor1', htmlspecialchars( $db->sf("product_desc"), ENT_QUOTES ), 'product_desc', '100%', '300', '55', '25' )
 ?>

Вставляем код:

<?php
$tabs->endTab();
$tabs->startTab( $dim_param_label, "param_page");

?>
<?php 
 $database->setQuery("SELECT * FROM `#__vm_product_param` ORDER BY `param_list_order` ASC");
 $list = $database->loadObjectList();
 echo '<br /><h2 style="padding:0 0 0 10px; font-size:17px;">'.$dim_param_label.':</h2><br />';
 foreach($list as $param) {
 $database->setQuery("SELECT `param_atr` FROM `#__vm_product_param_atr` WHERE `product_id`=".$product_id." AND `param_id`=".$param->param_id);
 $prod = $database->loadResult();
 echo '<table cellpadding="0" cellspacing="0">';
 echo '<tr>';
 echo '<td style="width:200px; padding:0 10px 5px 0; text-align: right;">'.$param->param_name.'</td>';
 echo '<td style="padding:0 0 5px 0;">';
 if (!empty($prod)) {
 echo '<input type="inputbox" class="inputbox" style="width:80%; padding:2px 0;" name="param_atr_'.$param->param_id.'" value="'.$prod.'" />';
 }
 else {
 echo '<input type="inputbox" class="inputbox" style="width:80%; padding:2px 0;" name="param_atr_'.$param->param_id.'" value="'.$param->param_atr.'" />';
 }
 echo '<input type="hidden" name="p_id_'.$param->param_id.'" style="width:80; padding:2px 0;%" value="'.$param->param_id.'" /></td></tr>';                
 echo '</table>';
 }
 echo '<br />';
?>

Теперь заходим в любой товар и видим появившуюся вкладку:

Страница пустая пока...

 

Шаг 2. Добавим таблицу в БД MySQL.

Выполняем в запрос в БД, не забываем менять префикс jos на свой:

CREATE  TABLE  `jos_vm_product_param_atr` (
`product_id` INT( 11  ) ,
 `param_id` INT( 11  ) ,
 `param_atr` VARCHAR( 64  )  CHARACTER  SET utf8 COLLATE utf8_general_ci
);

 

Шаг 3. Допишем функции.

Сначала допишем функцию add, чтобы параметры сохранялись при добавлении нового товара.

Открываем файл /administrator/components/com_virtuemart/classes/ps_product.php

После 370-372 срок:

$q = "INSERT INTO #__{vm}_product_mf_xref VALUES (";
 $q .= "'".$d['product_id']."', '".vmRequest::getInt('manufacturer_id')."')";
 $db->setQuery($q); $db->query();

Добавим наш код:

$db2 = new ps_DB;
 $db2->query('SELECT `param_id` FROM `#__vm_product_param`');
 $list = $db2->loadObjectList();
 foreach($list as $param) {
 $param_atr = $_POST['param_atr_'.$param->param_id];
 if(!empty($param_atr)) {
 $q = "INSERT INTO #__{vm}_product_param_atr (`product_id`, `param_id`, `param_atr`) VALUES ";
 $q .= "('".$d["product_id"]."', '".$param->param_id."', '".$param_atr."')";
 $db->query( $q );
 }
 }

Можете проверить. Создать новый продукт и внести параметры. Замечу, что параметры сохранятся, но редактироваться не будут, так как нужно дописать функцию update. Тут я немного завис.

На прошлом этапе мы прописали код для добавления параметров. Проще было бы добавлять в БД сразу все параметры, даже те, которые не заполнены при добавлении товара и хранить тупо в NULL.

Допустим для одного товара мы будем использовать параметры вес и длина, а для другого - ширина и высота. Писать в базу придётся всё равно все параметры и для первого и для второго товара. Я терпеть не могу, когда в базе хранится то, что, возможно, никогда и использоваться-то не будет. Поэтому решил пойти по чуть более сложному, но более правильному, на мой взгляд, пути.

Мы будем писать в базу не всё подряд, а только те параметры, которые были заполнены при добавлении / редактировании товара. Но тогда придётся делать несколько проверок:

  1. Если значения параметра для данного продукта ещё нет в базе и значение для него введено в поле, то мы запишем этот параметр в базу, как новый.
  2. Если значение параметра для данного продукта присутствует в базе и оно введено в поле, то обновим значение на новое. 
  3. Если значение параметра для данного продукта присутствует в базе, НО оно НЕ введено в поле, то удалим это значение из базы.

В этом же файле после строк 557-560:

} else {
 $q = "INSERT INTO #__{vm}_product_mf_xref (product_id,manufacturer_id) VALUES ('".$d['product_id']."','".vmRequest::getInt('manufacturer_id')."')";
 }
 $db->query($q);

Допишем свой код.

$db2 = new ps_DB;
 $db2->query('SELECT `param_id` FROM `#__vm_product_param`');
 $list = $db2->loadObjectList();
 foreach($list as $param) {
 $param_atr = $_POST['param_atr_'.$param->param_id];
 $db3 = new ps_DB;
 $db3->query('SELECT `param_atr` FROM `#__vm_product_param_atr` WHERE `param_id` = '.$param->param_id.' AND `product_id` = '.$d["product_id"]);
 $validate_param = $db3->loadResult();
 if($validate_param != '' && !empty($param_atr)) {
 $fields = array ('param_atr' => $param_atr );
 $db->buildQuery( 'UPDATE', '#__{vm}_product_param_atr', $fields,  'WHERE param_id = '.$param->param_id.' AND product_id = '.$d["product_id"]);
 $db->query();
 }
 else if ($validate_param == '' && !empty($param_atr)) {
 $q = "INSERT INTO #__{vm}_product_param_atr (`product_id`, `param_id`, `param_atr`) VALUES ";
 $q .= "('".$d["product_id"]."', '".$param->param_id."', '".$param_atr."')";
 $db->query( $q );
 }
 else if ($validate_param != '' && isset($param_atr)) {
 $q = "DELETE FROM `#__{vm}_product_param_atr` WHERE `param_id` =".$param->param_id." AND `product_id` = ".$d["product_id"];
 $db->query( $q );
 }
 }

Всё, можно проверить работоспособность.

Остался один момент. Когда товар удаляется, нам нужно стереть из базы все параметры, заданные для этого товара, поэтому в этом же файле, после 846-849 строк:

/* Delete attributes */
 $q  = "DELETE FROM #__{vm}_product_attribute_sku WHERE product_id='$product_id' ";
 $db->setQuery($q); $db->query();

Допишем свой код:

/* Удалить параметры при удалении товара */
 $q = "DELETE FROM `#__{vm}_product_param_atr` WHERE product_id='$product_id' ";
 $db->setQuery($q); $db->query();

 

ЧАСТЬ ТРЕТЬЯ. Вывод параметров  в карточке товара.

 

Тут всё просто. В используемый flypage вставляем код:

<?php 
 $db = new ps_DB;
 $db->setQuery("SELECT `#__vm_product_param`.`param_name`, `#__vm_product_param_atr`.`param_atr` FROM `#__vm_product_param` LEFT JOIN `#__vm_product_param_atr` ON `#__vm_product_param`.`param_id` =  `#__vm_product_param_atr`.`param_id` WHERE `#__vm_product_param_atr`.`product_id` = ".$product_id." AND `#__vm_product_param`.`param_publish` = 'Y' ORDER BY `#__vm_product_param`.`param_list_order` ASC, `#__vm_product_param`.`param_id` ASC");
 $list = $db->loadObjectList();
 echo '<table cellpadding="0" cellspacing="0">';
 foreach($list as $param) {
 echo '<tr>';
 echo '<td>'.$param->param_name.'</td>';
 echo '<td>'.$param->param_atr.'</td>';;
 echo '</tr>';
 }
 echo '</table>';
 ?>

Параметры вывелись. Оформляем как угодно через CSS. Всё, работа закончена.

Вывод параметров на странице товара

Вложения:
ФайлОписаниеРазмер файла
Скачать файл (administrator.zip)administrator.zipФайлы для добавления5 Kb
 

Вы можете отблагодарить автора:

WMR - R166832041362

WMZ - Z314865156270

QIWI - 9638061071

Яндекс деньги - 41001228750313


Комментарии 
 
#31 28.12.2013 16:52
Уважаемый, подскажите пожалуйста, хоть подтолкните к мысли. Как отобразить то же самое только в browse_1.php ? (в списке товаров категории). Вписал прямо туда, но результата ноль, только точка черная на том месте. Спасибо.
 
 
#30 19.10.2012 11:25
Значит сделал все нормально, Список параметров товара отображаються , сами параметры в товаре отображаються, но когда захожу в сам список то пишет что
"Forbidden
You don't have permission to access /http://localhost/vadim/administrator/index.php on this server." проверил снова все ли там где нада, все ок...
 
 
#29 18.10.2012 04:29
Кто где находится? flypage? В папке Вашего шаблона virtuemart.
 
 
#28 17.10.2012 16:37
Возникла проблема, сделал все как написано, но не уверен что последний пункт сделал правильно" Тут всё просто. В используемый flypage вставляем код:" где он находиться скажите пожалуста... или он у всех по разному?
 
 
#27 11.09.2012 20:06
А для какой версии эта инструкция?
 
 
#26 25.05.2012 11:44
Можно ли как-то добавлять свойства сразу через CSVI?
 
 
#25 23.04.2012 17:15
Сегодня делал доработку для еще одного клиента. Инструкция была проверена, отредактирована в соответствии с комментариями, устранены ошибки в описании.

Подтверждаю, инструкция полностью работоспособна!
 
 
#24 27.03.2012 14:01
Цитирую Павел:
Цитирую Дмитрий Краев:
Цитирую Павел:
Разобрался, они появляются сохраняются только тогда, тогда я создаю новую позицию, а текущих не сохраняется, жаль конечно что не получилось реализовать функцию update, крайне удобно...

Функция update реализована и описана в 3 шаге данной инструкции.

Вот она по какой-то причине не работает( Т.е. при создании новой позиции те поля которые я заполнил сохраняются, а вот если я пытаюсь что-то изменить - то ничего не происходит, только через phpmyadmin( сделал все согласно инструкции...

Все, мой косяк, ошибся в коде((( Теперь все работает, огромное спасибо! Реально очень полезная доработка!
 
 
#23 27.03.2012 12:15
Цитирую Дмитрий Краев:
Цитирую Павел:
Разобрался, они появляются сохраняются только тогда, тогда я создаю новую позицию, а текущих не сохраняется, жаль конечно что не получилось реализовать функцию update, крайне удобно...

Функция update реализована и описана в 3 шаге данной инструкции.

Вот она по какой-то причине не работает( Т.е. при создании новой позиции те поля которые я заполнил сохраняются, а вот если я пытаюсь что-то изменить - то ничего не происходит, только через phpmyadmin( сделал все согласно инструкции...
 
 
#22 27.03.2012 12:07
Цитирую Павел:
Разобрался, они появляются сохраняются только тогда, тогда я создаю новую позицию, а текущих не сохраняется, жаль конечно что не получилось реализовать функцию update, крайне удобно...

Функция update реализована и описана в 3 шаге данной инструкции.