Пишем модуль "Импорт товаров OpenCart", часть 2
Пришло время логического завершения саги под названием "Модуль импорта товаров в Opencart". Для тех, кто не читал первую часть, прошу ознакомиться с содержимым первой статьи: Пишем модуль "Импорт товаров OpenCart", часть 1.
Итак, в тот раз мы остановились на том, что создали все файлы заглушки и сейчас вопрос в реализации непосредственного парсинга и сохранения данных из CSV в БД Opencart.
Ссылка на Bitbucket с работающим плагином: bitbucket.org/Kolpikov/opencart-product-import-module
Тепреь нужно понять, в каком формате нужно передать данные в модель для сохранения товара. В данном случае самый простой вариант состоит в том, чтобы подсмотреть как система сохраняет товары к себе в админке и скопировать данный процесс. Для этого я открываю метод addProduct() в модели admin/model/catalog/product.php:3 и ставлю breakpoint в IDE в первой же строчке к тела данного метода модели.
Затем открывю админ панель, заполняю поля, которые меня интересуют и жму добавить товар. В итоге я могу видеть массив $data, который система передает в модель:
Если нет дебаггера, то просто сделайте var_dump и die перед вызовом сохранения в БД, чтоб увидеть сформированный массив.
Теперь мы знаем, какие данные от нас ожидает получить метод addProduct(), принадлежащий модели catalog/product и можем собрать аналогичный массив с нужными полями
Теперь, когда понятно как формировать массив - можно переходить к кодингу.
1. Пишем метод импорта товаров из CSV
Открываем файл admin/controller/tool/import.php и добавляем после строки:
$this->document->setTitle($this->language->get('heading_title'));
Следующий код:
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->user->hasPermission('modify', 'tool/import')) {
if (is_uploaded_file($this->request->files['import']['tmp_name'])) {
$file = $this->request->files['import']['tmp_name'];
} else {
$file = false;
}
if ($file && ($handle = fopen($file, "r")) !== false ) {
$this->import_products($handle);
fclose($handle);
$this->session->data['success'] = $this->language->get('text_success');
$this->response->redirect($this->url->link('tool/import', 'token=' . $this->session->data['token'], true));
} else {
$this->error['warning'] = $this->language->get('error_empty');
}
}
Данный код отвечает за то, чтобы проверить есть ли у текущего пользователя права модицикации для страницы tool/import, и что файл с данными был загружен, и если все норм - пробует открыть файл для чтения и передать ресурс в метод import_products(), который вытащий построчно все данные о товарах.
В общем-то не важно куда именно вставить этот кусочек кода. Но полистав контроллеры Opencart, я пришел к выводу, что в их эко-системе такие вызовы уместней всего располагать именно вот так.
Теперь реализуем метод import_products() в нашем контроллере:
private function import_products($handle)
{
$this->load->model('catalog/product');
$this->load->model('localisation/language');
$languages = $this->model_localisation_language->getLanguages();
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) // Читает строку из файла и производит разбор данных CSV
{
$product_description = [];
foreach ($languages as $language) {
$product_description[$language['language_id']] = [
'name' => $data[3], // имя
'description' => $data[4], //item_desc
'meta_title' => $data[3], // title = имя
'meta_h1' => $data[3], // title = имя
'meta_description' => $data[13],
'meta_keyword' => $data[12],
'tag' => '',
];
}
$prod_data = array(
'product_description' => $product_description,
'model' => $data[2], //артикул
'sku' => "",
'upc' => "",
'ean' => "",
'jan' => "",
'isbn' => "",
'mpn' => "",
'location' => "",
'price' => $data[10],
'tax_class_id' => "0",
'quantity' => "1",
'minimum' => "1",
'subtract' => "1",
'stock_status_id' => "6", //статус, когда нет в наличии
'shipping' => "1",
'keyword' => $data[6], //seo url
'date_available' => $data[19],
'length' => "",
'width' => "",
'height' => "",
'length_class_id' => "1",
'weight' => "",
'weight_class_id' => "1",
'status' => $data[16],
'sort_order' => "1",
'manufacturer' => "",
'manufacturer_id' => "0",
'category' => '',
'product_category' => explode(',' , $data[1]),
'filter' => "",
'product_store' => array("0"),
'download' => "",
'related' => "",
'option' => "",
'image' => "",
'points' => "",
'product_reward' => array('1' => array('points' => "")),
'product_layout' => array(""),
'date_added' => $data[18],
'supplier_id' => (!empty($data[8])) ? $data[8] : '',
'cost' => (!empty($data[9])) ? $data[9] : '',
'notes' => (!empty($data[17])) ? $data[17] : '',
);
if (!empty($data[11])) {
$prod_data['product_discount'] = array(
array('customer_group_id' => '1',
'quantity' => "",
'priority' => "",
'price' => $data[11],
'date_start' => "",
'date_end' => ""
)
);
}
if ( !empty($data[20]) ) // Основное фото
$prod_data["image"] = $data[20];
if ( !empty($data[21]) ) // Доп. фото
{
$other_photos = explode(';',$data[21]);
if( ($key = array_search($data[20],$other_photos)) !== false )
unset($other_photos[$key]);
foreach ($other_photos as $other_photo) {
$prod_data["product_image"][] = array('image' => $other_photo,
'sort_order' => ''
);
}
}
$this->model_catalog_product->addProduct($prod_data);
}
}
Ну вот и всё! Логика готова!
2. Подготавливаем модуль к автоматической установке
Чтобы иметь возможность автоматически устанавливать модуль через менеджер модулей Opencart нам нужно вынести все файлы в отдельную папку, расположить их в порядке, как я показывал на скрин-шоте в первом уроке и затем запаковать в zip архив.
После чего модуль можно легко добавлять на различные Opencart'ы версии 2.2.0.0 с минимальными затратами времени! Не забудьте только добавить права для группы пользователей на просмотр и редактирование tool/import
Всем спасибо за внимание!
Исходники тут: bitbucket.org/Kolpikov/opencart-product-import-module