На форуме 9558 тем, 76452 сообщений, 44664 участников
тема · 2 839 просмотров · 24 ответа

Opencart 3. Добавить новое поле в oc_ product_image

Общие вопросы
читают: 0 участников и 1 гость
порядок
1 июл 2019 13:19#1
Добрый день. Я новичок, стараюсь самостоятельно разобраться, но сейчас в тупике.

Нужно добавить поле описания для дополнительных изображений товара во вкладке "изображения".

Что я сделал. В admin\model\catalog\product.php строка 76 и 222 вставил (выделено):
code
        if (isset($data['product_image'])) {
            foreach ($data['product_image'] as $product_image) {
               
                    $this->db->query("INSERT INTO " . DB_PREFIX . "product_image SET product_id = '" . (int)$product_id . "', image = '" . $this->db->escape($product_image['image']) . "', sort_order = '" . (int)$product_image['sort_order'] . "', language_id = '" . (int)$language_id . "', img_description = '" .  $this->db->escape($product_image['img_description']) . "'");
               
            }
        }


В admin\controller\catalog\product.php строка 1079:
code
$data['product_images'][] = array(
            'image' => $image,
            'thumb' => $this->model_tool_image->resize($thumb, 100, 100),
            'sort_order' => $product_image['sort_order'],
            'img_description' => $product_image['img_description']
         );


В admin\view\template\catalog\product_form.twig вставил поля с привязкой к языку (на сайте два языка)
code
<td class="text-right">{% for language in languages %}
                      <div class="input-group"><span class="input-group-addon"><img src="language/{{ language.code }}/{{ language.code }}.png" title="{{ language.name }}" /></span>
                        <textarea name="product_image[{{ image_row }}][{{ language.language_id }}][img_description]" rows="5" placeholder="{{ entry_img_description }}" class="form-control">{{ product_image[language.language_id] ? product_image[language.language_id].img_description }}</textarea>
                      </div>
                      {% endfor %}
                    </td>


В БД в таблице oc_product_image добавил поля img_description и language_id (id языка добавил в PRIMARY и аттрибуи "первичный" - использую OpenServer).

После сохранения изменений, обновил во вкладке модификаторы.

К части вывода полей на сайте не перешел, т.к. полезли ошибки при обновлении карточки товара:
Цитата:Notice: Undefined index: img_description in **\system\storage\modification\admin\model\catalog\product.php on line 250Notice: Undefined index: img_description in **\system\storage\modification\admin\model\catalog\product.php on line 250Warning: Cannot modify header information - headers already sent by (output started at **\admin\controller\startup\error.php:34) in **\system\library\response.php on line 36


Проверил данный файл, в указанном месте (строка 250) ничего нет, а в местах касающихся product_image внесены соответствующие изменения описанные выше.

Добрые люди, помогите решить задачу.
1 июл 2019 14:41#3
Chukcha написал(а): ↑https://shop.opencart-russia.ru/custom-title-img-image

Спасибо за ответ. Но у меня Opencart 3.x, и необходимо добавить новое поле конкретно к дополнительным изображениям с учетом двуязычности.

Возможно подскажите что я мог упустить?
1 июл 2019 16:08#4
euxos написал(а): ↑В БД в таблице oc_product_image добавил поля img_description и language_id (id языка добавил в PRIMARY и аттрибуи "первичный" - использую OpenServer).

отдельную таблицу для описания изображений
1 июл 2019 16:12#5
fanatic написал(а): ↑отдельную таблицу для описания изображений

То есть, вместо полей, создать новую таблицу? и в модуле и контроллере привязываться не к product_image?
1 июл 2019 17:43#7
таблица
code
CREATE TABLE IF NOT EXISTS `oc_product_image_description` (
  `image_id` int(11) NOT NULL,
  `image_product_id` int(11) NOT NULL,
  `language_id` int(2) NOT NULL,
  `image_description` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `oc_product_image_description`
  ADD PRIMARY KEY (`image_id`,`image_product_id`,`language_id`);

контроллер
php
        $data['product_images'] = array();

foreach ($product_images as $product_image) {
if (is_file(DIR_IMAGE . $product_image['image'])) {
$image = $product_image['image'];
$thumb = $product_image['image'];
} else {
$image = '';
$thumb = 'no_image.png';
}

// desc image start
$data['entry_image_description'] = $this->language->get('entry_image_description');
if (isset($this->request->post['product_image'])) {
$p_i_d = $product_image['product_image_description'];
} else {
$p_i_d = $this->model_catalog_product->getImageDescrption($product_image['product_image_id'], $this->request->get['product_id']);
}
// desc image end

$data['product_images'][] = array(
'image' => $image,
'thumb' => $this->model_tool_image->resize($thumb, 100, 100),
'sort_order' => $product_image['sort_order'],
// desc image start
'product_image_description' => $p_i_d
// desc image end
);
}

модель для editProdct. для addProductc сделаете по аналогии. и в deleteProduc нужно добавить удаление
php
 $this->db->query("DELETE FROM " . DB_PREFIX . "product_image WHERE product_id = '" . (int) $product_id . "'");
// desc image start

$this->db->query("DELETE FROM " . DB_PREFIX . "product_image_description WHERE image_product_id = '" . (int) $product_id . "'");

// desc imat end

if (isset($data['product_image'])) {
foreach ($data['product_image'] as $product_image) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_image SET product_id = '" . (int) $product_id . "', image = '" . $this->db->escape($product_image['image']) . "', sort_order = '" . (int) $product_image['sort_order'] . "'");
// desc image start

$image_id = $this->db->getLastId();

if(!empty($product_image['product_image_description'])){
foreach($product_image['product_image_description'] as $l_id => $value){

$this->db->query("INSERT INTO " . DB_PREFIX . "product_image_description SET image_id = '" . (int) $image_id . "', language_id = '" . (int) $l_id . "', image_product_id = '" . (int) $product_id . "', image_description = '" . $this->db->escape($value['text']) . "'");
}

}

// desc imag end
}
}

еще модель

php
    public function getImageDescrption($image_id, $product_id){
$description_image = array();
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_image_description WHERE image_id = '" . (int)$image_id . "' AND image_product_id = '" . (int) $product_id . "'");

if($query->rows){
foreach($query->rows as $desc){
$description_image[$desc['language_id']]['text'] = $desc['image_description'];
}
}

return $description_image;

}

шаблон
html
              <div class="table-responsive">
<table id="images" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<td class="text-left">{{ entry_additional_image }}</td>
<td class="text-right">{{ entry_image_description }}</td>
<td class="text-right">{{ entry_sort_order }}</td>
<td></td>
</tr>
</thead>
<tbody>

{% set image_row = 0 %}
{% for product_image in product_images %}
<tr id="image-row{{ image_row }}">
<td class="text-left"><a href="" id="thumb-image{{ image_row }}" data-toggle="image" class="img-thumbnail"><img src="{{ product_image.thumb }}" alt="" title="" data-placeholder="{{ placeholder }}" /></a>
<input type="hidden" name="product_image[{{ image_row }}][image]" value="{{ product_image.image }}" id="input-image{{ image_row }}" /></td>

{# desc image start #}

<td class="text-left">
{% for language in languages %}
<div class="input-group"><span class="input-group-addon"><img src="language/{{ language.code }}/{{ language.code }}.png" title="{{ language.name }}" /></span>
<textarea name="product_image[{{ image_row }}][product_image_description][{{ language.language_id }}][text]" rows="5" placeholder="{{ entry_text }}" class="form-control">{{ product_image.product_image_description[language.language_id] ? product_image.product_image_description[language.language_id].text }}</textarea>
</div>
{% endfor %}
</td>

{# desc image end #}

<td class="text-right"><input type="text" name="product_image[{{ image_row }}][sort_order]" value="{{ product_image.sort_order }}" placeholder="{{ entry_sort_order }}" class="form-control" /></td>
<td class="text-left"><button type="button" onclick="$('#image-row{{ image_row }}').remove();" data-toggle="tooltip" title="{{ button_remove }}" class="btn btn-danger"><i class="fa fa-minus-circle"></i></button></td>
</tr>
{% set image_row = image_row + 1 %}
{% endfor %}
</tbody>

<tfoot>
<tr>
<td colspan="2"></td>
<td class="text-left"><button type="button" onclick="addImage();" data-toggle="tooltip" title="{{ button_image_add }}" class="btn btn-primary"><i class="fa fa-plus-circle"></i></button></td>
</tr>
</tfoot>
</table>
</div>

локализация
php
$_['entry_image_description'] = 'Описание изображения';

и еще нужно в javacript добавить вывод поля с описанием. по аналогии как в шаблоне
1 июл 2019 19:45#8
fanatic написал(а): ↑таблица
code
CREATE TABLE IF NOT EXISTS `oc_product_image_description` (
  `image_id` int(11) NOT NULL,
  `image_product_id` int(11) NOT NULL,
  `language_id` int(2) NOT NULL,
  `image_description` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `oc_product_image_description`
  ADD PRIMARY KEY (`image_id`,`image_product_id`,`language_id`);

контроллер
php
        $data['product_images'] = array();

foreach ($product_images as $product_image) {
if (is_file(DIR_IMAGE . $product_image['image'])) {
$image = $product_image['image'];
$thumb = $product_image['image'];
} else {
$image = '';
$thumb = 'no_image.png';
}

// desc image start
$data['entry_image_description'] = $this->language->get('entry_image_description');
if (isset($this->request->post['product_image'])) {
$p_i_d = $product_image['product_image_description'];
} else {
$p_i_d = $this->model_catalog_product->getImageDescrption($product_image['product_image_id'], $this->request->get['product_id']);
}
// desc image end

$data['product_images'][] = array(
'image' => $image,
'thumb' => $this->model_tool_image->resize($thumb, 100, 100),
'sort_order' => $product_image['sort_order'],
// desc image start
'product_image_description' => $p_i_d
// desc image end
);
}

модель для editProdct. для addProductc сделаете по аналогии. и в deleteProduc нужно добавить удаление
php
 $this->db->query("DELETE FROM " . DB_PREFIX . "product_image WHERE product_id = '" . (int) $product_id . "'");
// desc image start

$this->db->query("DELETE FROM " . DB_PREFIX . "product_image_description WHERE image_product_id = '" . (int) $product_id . "'");

// desc imat end

if (isset($data['product_image'])) {
foreach ($data['product_image'] as $product_image) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_image SET product_id = '" . (int) $product_id . "', image = '" . $this->db->escape($product_image['image']) . "', sort_order = '" . (int) $product_image['sort_order'] . "'");
// desc image start

$image_id = $this->db->getLastId();

if(!empty($product_image['product_image_description'])){
foreach($product_image['product_image_description'] as $l_id => $value){

$this->db->query("INSERT INTO " . DB_PREFIX . "product_image_description SET image_id = '" . (int) $image_id . "', language_id = '" . (int) $l_id . "', image_product_id = '" . (int) $product_id . "', image_description = '" . $this->db->escape($value['text']) . "'");
}

}

// desc imag end
}
}

еще модель

php
    public function getImageDescrption($image_id, $product_id){
$description_image = array();
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_image_description WHERE image_id = '" . (int)$image_id . "' AND image_product_id = '" . (int) $product_id . "'");

if($query->rows){
foreach($query->rows as $desc){
$description_image[$desc['language_id']]['text'] = $desc['image_description'];
}
}

return $description_image;

}

шаблон
html
              <div class="table-responsive">
<table id="images" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<td class="text-left">{{ entry_additional_image }}</td>
<td class="text-right">{{ entry_image_description }}</td>
<td class="text-right">{{ entry_sort_order }}</td>
<td></td>
</tr>
</thead>
<tbody>

{% set image_row = 0 %}
{% for product_image in product_images %}
<tr id="image-row{{ image_row }}">
<td class="text-left"><a href="" id="thumb-image{{ image_row }}" data-toggle="image" class="img-thumbnail"><img src="{{ product_image.thumb }}" alt="" title="" data-placeholder="{{ placeholder }}" /></a>
<input type="hidden" name="product_image[{{ image_row }}][image]" value="{{ product_image.image }}" id="input-image{{ image_row }}" /></td>

{# desc image start #}

<td class="text-left">
{% for language in languages %}
<div class="input-group"><span class="input-group-addon"><img src="language/{{ language.code }}/{{ language.code }}.png" title="{{ language.name }}" /></span>
<textarea name="product_image[{{ image_row }}][product_image_description][{{ language.language_id }}][text]" rows="5" placeholder="{{ entry_text }}" class="form-control">{{ product_image.product_image_description[language.language_id] ? product_image.product_image_description[language.language_id].text }}</textarea>
</div>
{% endfor %}
</td>

{# desc image end #}

<td class="text-right"><input type="text" name="product_image[{{ image_row }}][sort_order]" value="{{ product_image.sort_order }}" placeholder="{{ entry_sort_order }}" class="form-control" /></td>
<td class="text-left"><button type="button" onclick="$('#image-row{{ image_row }}').remove();" data-toggle="tooltip" title="{{ button_remove }}" class="btn btn-danger"><i class="fa fa-minus-circle"></i></button></td>
</tr>
{% set image_row = image_row + 1 %}
{% endfor %}
</tbody>

<tfoot>
<tr>
<td colspan="2"></td>
<td class="text-left"><button type="button" onclick="addImage();" data-toggle="tooltip" title="{{ button_image_add }}" class="btn btn-primary"><i class="fa fa-plus-circle"></i></button></td>
</tr>
</tfoot>
</table>
</div>

локализация
php
$_['entry_image_description'] = 'Описание изображения';

и еще нужно в javacript добавить вывод поля с описанием. по аналогии как в шаблоне

Спасибо! В базу всё отлично добавляется.
javascript тот что в *\catalog\view\javascript\common.js или *\admin\view\javascript\common.js ?
И для вывода на сайте нужно добавить переменную в *\catalog\controller\product\product.php ?

пробовал сюда:
code
$data['products'][] = array(
....
     'image_description' => $this->model_catalog_product->getImageDescrption($result['product_id']),
....
1 июл 2019 19:45#9
euxos написал(а): ↑Спасибо за ответ. Но у меня Opencart 3.x,

Есть и для 3-ки

Отдельную таблицу? нет смысла


fanatic написал(а): ↑и еще нужно в javacript добавить вывод поля с описанием. по аналогии как в шаблоне

Зачем? Для чего этого надо? Это обыкновенный input

Как показывает практика, если у вас около 100 товаров и на каждый по 5-6 картинок - то описания уже никто не заполняет

Для уникализации описаний достаточно модуля
1 июл 2019 20:05#10
fanatic написал(а): ↑таблица
code
CREATE TABLE IF NOT EXISTS `oc_product_image_description` (
  `image_id` int(11) NOT NULL,
  `image_product_id` int(11) NOT NULL,
  `language_id` int(2) NOT NULL,
  `image_description` text NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

ALTER TABLE `oc_product_image_description`
  ADD PRIMARY KEY (`image_id`,`image_product_id`,`language_id`);

контроллер
php
        $data['product_images'] = array();

foreach ($product_images as $product_image) {
if (is_file(DIR_IMAGE . $product_image['image'])) {
$image = $product_image['image'];
$thumb = $product_image['image'];
} else {
$image = '';
$thumb = 'no_image.png';
}

// desc image start
$data['entry_image_description'] = $this->language->get('entry_image_description');
if (isset($this->request->post['product_image'])) {
$p_i_d = $product_image['product_image_description'];
} else {
$p_i_d = $this->model_catalog_product->getImageDescrption($product_image['product_image_id'], $this->request->get['product_id']);
}
// desc image end

$data['product_images'][] = array(
'image' => $image,
'thumb' => $this->model_tool_image->resize($thumb, 100, 100),
'sort_order' => $product_image['sort_order'],
// desc image start
'product_image_description' => $p_i_d
// desc image end
);
}

модель для editProdct. для addProductc сделаете по аналогии. и в deleteProduc нужно добавить удаление
php
 $this->db->query("DELETE FROM " . DB_PREFIX . "product_image WHERE product_id = '" . (int) $product_id . "'");
// desc image start

$this->db->query("DELETE FROM " . DB_PREFIX . "product_image_description WHERE image_product_id = '" . (int) $product_id . "'");

// desc imat end

if (isset($data['product_image'])) {
foreach ($data['product_image'] as $product_image) {
$this->db->query("INSERT INTO " . DB_PREFIX . "product_image SET product_id = '" . (int) $product_id . "', image = '" . $this->db->escape($product_image['image']) . "', sort_order = '" . (int) $product_image['sort_order'] . "'");
// desc image start

$image_id = $this->db->getLastId();

if(!empty($product_image['product_image_description'])){
foreach($product_image['product_image_description'] as $l_id => $value){

$this->db->query("INSERT INTO " . DB_PREFIX . "product_image_description SET image_id = '" . (int) $image_id . "', language_id = '" . (int) $l_id . "', image_product_id = '" . (int) $product_id . "', image_description = '" . $this->db->escape($value['text']) . "'");
}

}

// desc imag end
}
}

еще модель

php
    public function getImageDescrption($image_id, $product_id){
$description_image = array();
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_image_description WHERE image_id = '" . (int)$image_id . "' AND image_product_id = '" . (int) $product_id . "'");

if($query->rows){
foreach($query->rows as $desc){
$description_image[$desc['language_id']]['text'] = $desc['image_description'];
}
}

return $description_image;

}

шаблон
html
              <div class="table-responsive">
<table id="images" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<td class="text-left">{{ entry_additional_image }}</td>
<td class="text-right">{{ entry_image_description }}</td>
<td class="text-right">{{ entry_sort_order }}</td>
<td></td>
</tr>
</thead>
<tbody>

{% set image_row = 0 %}
{% for product_image in product_images %}
<tr id="image-row{{ image_row }}">
<td class="text-left"><a href="" id="thumb-image{{ image_row }}" data-toggle="image" class="img-thumbnail"><img src="{{ product_image.thumb }}" alt="" title="" data-placeholder="{{ placeholder }}" /></a>
<input type="hidden" name="product_image[{{ image_row }}][image]" value="{{ product_image.image }}" id="input-image{{ image_row }}" /></td>

{# desc image start #}

<td class="text-left">
{% for language in languages %}
<div class="input-group"><span class="input-group-addon"><img src="language/{{ language.code }}/{{ language.code }}.png" title="{{ language.name }}" /></span>
<textarea name="product_image[{{ image_row }}][product_image_description][{{ language.language_id }}][text]" rows="5" placeholder="{{ entry_text }}" class="form-control">{{ product_image.product_image_description[language.language_id] ? product_image.product_image_description[language.language_id].text }}</textarea>
</div>
{% endfor %}
</td>

{# desc image end #}

<td class="text-right"><input type="text" name="product_image[{{ image_row }}][sort_order]" value="{{ product_image.sort_order }}" placeholder="{{ entry_sort_order }}" class="form-control" /></td>
<td class="text-left"><button type="button" onclick="$('#image-row{{ image_row }}').remove();" data-toggle="tooltip" title="{{ button_remove }}" class="btn btn-danger"><i class="fa fa-minus-circle"></i></button></td>
</tr>
{% set image_row = image_row + 1 %}
{% endfor %}
</tbody>

<tfoot>
<tr>
<td colspan="2"></td>
<td class="text-left"><button type="button" onclick="addImage();" data-toggle="tooltip" title="{{ button_image_add }}" class="btn btn-primary"><i class="fa fa-plus-circle"></i></button></td>
</tr>
</tfoot>
</table>
</div>

локализация
php
$_['entry_image_description'] = 'Описание изображения';

и еще нужно в javacript добавить вывод поля с описанием. по аналогии как в шаблоне

Имел ввиду, как теперь вывести описания под доп.картинками?
1 июл 2019 20:14#11
Chukcha написал(а): ↑Зачем? Для чего этого надо? Это обыкновенный input

я об этом
<button type="button" onclick="addImage();" data-toggle="tooltip" title="" class="btn btn-primary" data-original-title="Добавить"><i class="fa fa-plus-circle">
1 июл 2019 20:17#12
Chukcha написал(а): ↑Отдельную таблицу? нет смысла

а что, все пихать в product_image? ладно если без language, а для разных языков?
или я что-то не понимаю?
1 июл 2019 20:20#13
euxos написал(а): ↑javascript тот что в *\catalog\view\javascript\common.js или *\admin\view\javascript\common.js ?

нет, в файле шаблона в
code
function addImage() {
1 июл 2019 20:20#14
fanatic написал(а): ↑я об этом
<button type="button" onclick="addImage();" data-toggle="tooltip" title="" class="btn btn-primary" data-original-title="Добавить"><i class="fa fa-plus-circle">

Кнопку сделать получилось. Спасибо!
1 июл 2019 20:22#15
euxos написал(а): ↑И для вывода на сайте нужно добавить переменную в *\catalog\controller\product\product.php ?

для начала, нужно достать из базы
1 июл 2019 20:23#16
fanatic написал(а): ↑нет, в файле шаблона в
code
function addImage() {

Осталось понять как вывести описание на сайте. Извините за наглость.
Нужно добавить переменную *\catalog\controller\product\product.php - правильно понимаю? И функцией getImageDescrption передать в нее значение из БД?
1 июл 2019 20:25#17
euxos написал(а): ↑Имел ввиду, как теперь вывести описания под доп.картинками?

в контроллере достать из базы и передать в шаблон
1 июл 2019 20:30#18
euxos написал(а): ↑Осталось понять как вывести описание на сайте.

где вы хотите вывести? в карточке товара под изображениями?
1 июл 2019 20:31#19
fanatic написал(а): ↑где вы хотите вывести? в карточке товара под изображениями?

да, чтобы описания подгружались вместе с изображениями.
1 июл 2019 20:49#20
fanatic написал(а): ↑а что, все пихать в product_image? ладно если без language, а для разных языков?
или я что-то не понимаю?

можно паковать через json или serialize

fanatic написал(а): ↑где вы хотите вывести? в карточке товара под изображениями?

под изображениями? или в атрибутах?
сообщения 1–20 из 25
Чтобы ответить, войдите или зарегистрируйтесь.

Похожие темы