UMIhelp

Разработка дополнительного функционала => Custom макросы => Тема начата: muldy от 02 Октября 2013, 15:07:45

Название: Новый формат импорта CSV?
Отправлено: muldy от 02 Октября 2013, 15:07:45
Здравствуйте!
Есть готовый файл csv, но он кардинально различается отображением чем у umi, как реализовать подстановку и замену полей на нужные, те те которые принимает система!?
Или проще говоря использовать другой щаблон импорта данных?
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 03 Октября 2013, 00:36:23
Нашел инструкцию здесь:
http://wiki.umisoft.ru/%D0%94%D0%BE%D0%B1%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BD%D0%BE%D0%B2%D0%BE%D0%B3%D0%BE_%D1%81%D0%BF%D0%BB%D0%B8%D1%82%D1%82%D0%B5%D1%80%D0%B0_%D0%B4%D0%BB%D1%8F_%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82%D0%B0_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85
Сделал по ней но не работает, пишет: unknown umidump version
Сталкивался ли кто нибудь с такой проблемой?
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 04 Октября 2013, 18:41:56
Встречался. Использую такую заготовки для csv_test импорта и её модификации

<?php
class csv_testSplitter extends umiImportSplitter {

protected function readDataBlock() {
// xml-пустышка
$doc = new DOMDocument("1.0", "utf-8");
$doc->formatOutput = XML_FORMAT_OUTPUT;
$rootNode = $doc->createElement("umidump");
$doc->appendChild($rootNode);
$rootNode->setAttribute('version', '2.0');
// текущее смещение
$index = ($this->offset) ? $this->offset : 0;
//Какие-то действия, в зависимости от текущего смещения
$start = ($this->offset) ? $this->offset + 1 : 1;
$end = ($this->offset) ? $start + $this->block_size - 1: $this->block_size;
$handle = fopen($this->file_path, "r");


$row = 1;
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
if($row == 1) {
$row++;
continue;
}

if($row >= $start and $row <= $end){
// строка разбита в массив по колонкам
// например $data[0] это значение первой колонки в вашем сым текущей строки
}
if($row > $end) break;
$row++; 
}
fclose($handle);
$this->offset += $this->block_size;

// условие для остановки цикла, которое необходимо настроить
if (!$data) $this->complete = true;

//тестовый лог
//file_put_contents(CURRENT_WORKING_DIR .'/traceajax.txt', $index.';', FILE_APPEND);

return $doc;
}

public function translate(DomDocument $doc) {
return $doc->saveXML();
}
}
?>


Есть 2 особенности:
1. такой импорт не отдает результат в виде статуса, сколько страниц создано, изменено и т.д. так как все происходит без участия umidump формата.
2. иногда из-за необходимости обработки русских символов или текста в кавычках работаю не с fgetcsv, а с fgets функцией чтения строки нашего файла. Плюс, иногда навешиваю обработку строки для борьбы с проблемами разных кодировок (обычно, csv приходят от клиента в win-1251 формате, а в системе используется utf8)
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 06 Октября 2013, 16:54:19
А где именно происходит обработка столбцов?
Файл csv имеет абсолютно другой вид, отличный от вида umi, и кстати попробывал ваш вариант, не работает(!
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 06 Октября 2013, 21:48:47
А где именно происходит обработка столбцов?

в моем пример, есть комментарий где показано как обратиться к первому столбцу
Цитировать
// например $data[0] это значение первой колонки в вашем сым текущей строки

или вы о чем-то другом спрашиваете?
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 06 Октября 2013, 22:46:24
Да с этим разобрался, ваш пример я так понимаю не рабочий? Правильно те это не готовый метод?
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 06 Октября 2013, 23:10:12
Цитировать
Правильно те это не готовый метод?

Этот вопрос не понял.

Код вырезан из рабочего кода, но вырезался прямо сюда в форум, так что за работоспособность не могу поручиться.
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 06 Октября 2013, 23:41:42
Да я имею ввиду что, этот код напрямую не будет работать?
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 07 Октября 2013, 03:34:45
ну... должен быть рабочим или близким к этому. Понятно, что в нем нет "начинки", то есть там где у вас будет обработка строк из csv файла (после строчки if($row >= $start and $row <= $end){) нужно вставить создание новых товаров или что-то еще, в зависимости от того что у вас в csv и по какой логике он должен импортироваться в систему.
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 07 Октября 2013, 11:13:38
А можете пример показать, как это будет описано например есть столбцы, у меня: 1 - Vendor, 2 - Name
Ну хотя бы на этих примерах?
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 08 Октября 2013, 17:19:08
пример чего? все зависит от логики, например вы хотите создавать новые страницы определенного типа, то примерно так:

<?php
...
if($row >= $start and $row <= $end){
$parent_id = 99; //id раздела куда будут создаваться товары
$hierarchy_type_id = umiHierarchyTypesCollection::getInstance()->getTypeByName("catalog", "object")->getId();
$hierarchy_type = umiHierarchyTypesCollection::getInstance()->getType($hierarchy_type_id);
$object_type_id = umiObjectTypesCollection::getInstance()->getBaseType($hierarchy_type->getName(), $hierarchy_type->getExt());
        $perm = permissionsCollection::getInstance();
        $guestId= $perm->getGuestId(); // получаем id гостя
        $permLevel=1; // ставим права на просмотр всем пользователям


$vendor = data[0];
$name = data[1];

//Creating page...
$page_id = $hierarchy->addElement($parent_id, $hierarchy_type_id, $name, $name, $object_type_id);
$perm->setElementPermissions($guestId,$page_id,$permLevel);
 
$page = $hierarchy->getElement($page_id, true);

$page->setIsActive(true);
$page->h1 = $name;
$page->vendor = $vendor; // записываем производителя в поле с именем "vendor"

$page->commit();
}
...
?>



Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 08 Октября 2013, 20:45:42
Круто, СПАСИБО, как раз то что и надо было показать в примере, взял себе!!!
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 08 Октября 2013, 22:29:06
В общем попробовал в итоге получил такой код:

<?php
class csv_testSplitter extends umiImportSplitter {

  protected function readDataBlock() {
    // xml-пустышка
    $doc = new DOMDocument("1.0", "utf-8");
    $doc->formatOutput = XML_FORMAT_OUTPUT;
    $rootNode = $doc->createElement("umidump");
    $doc->appendChild($rootNode);
    $rootNode->setAttribute('version', '2.0');
    // текущее смещение
    $index = ($this->offset) ? $this->offset : 0;
    //Какие-то действия, в зависимости от текущего смещения
    $start = ($this->offset) ? $this->offset + 1 : 1;
    $end = ($this->offset) ? $start + $this->block_size - 1: $this->block_size;
    $handle = fopen($this->file_path, "r");
   
   
    $row = 1;
    while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
      if($row == 1) {
        $row++;
        continue;
      }
     
      if($row >= $start and $row <= $end){

        $parent_id = 187; //id раздела куда будут создаваться товары
        $hierarchy_type_id = umiHierarchyTypesCollection::getInstance()->getTypeByName("catalog", "object")->getId();
        $hierarchy_type = umiHierarchyTypesCollection::getInstance()->getType($hierarchy_type_id);
        $object_type_id = umiObjectTypesCollection::getInstance()->getBaseType($hierarchy_type->getName(), $hierarchy_type->getExt());
        $perm = permissionsCollection::getInstance();
        $guestId= $perm->getGuestId(); // получаем id гостя
        $permLevel=1; // ставим права на просмотр всем пользователям
         
        $vendor = data[0];
        $name = data[1];
         
          //Creating page...

        $page_id = $hierarchy->addElement($parent_id, $hierarchy_type_id, $name, $name, $object_type_id);
        $perm->setElementPermissions($guestId,$page_id,$permLevel);
           
        $page = $hierarchy->getElement($page_id, true);
       
        $page->setIsActive(true);
        $page->h1 = $name;
        $page->vendor = $vendor; // записываем производителя в поле с именем "vendor"
       
        $page->commit();

      }
      if($row > $end) break;
      $row++; 
    }
    fclose($handle);
    $this->offset += $this->block_size;

    // условие для остановки цикла, которое необходимо настроить
    if (!$data) $this->complete = true;
   
    //тестовый лог
    //file_put_contents(CURRENT_WORKING_DIR .'/traceajax.txt', $index.';', FILE_APPEND);

    return $doc;
  }

  public function translate(DomDocument $doc) {
    return $doc->saveXML();
  }
}
?>

В результате при импорте система пише ошибка разбора данных!
В чем проблема не пойму?
Есть предположение что вот в этой строке:

        $vendor = data[0];
        $name = data[1];
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 08 Октября 2013, 23:11:17
если где-то косяк, то скорее всего в коде (начиная с банального синтаксиса).

при импорте через модуль обмен данных, включи firebug (или его аналог) и там будут отображаться ajax запросы. Как увидишь ошибку, рассмотри внимательно последний ajax запрос (или открой его в новом окне) , не забывая при этом включить debug в config.ini. Скорее всего, ошибка сразу же станет явной.
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 08 Октября 2013, 23:33:30
Да спасибо отследил, действительно было несколько недоработок! теперь все работает!
Вот готовый код, это если кому пригодится:

<?php
class csv_testSplitter extends umiImportSplitter {

  protected function readDataBlock() {
    // xml-пустышка
    $doc = new DOMDocument("1.0", "utf-8");
    $doc->formatOutput = XML_FORMAT_OUTPUT;
    $rootNode = $doc->createElement("umidump");
    $doc->appendChild($rootNode);
    $rootNode->setAttribute('version', '2.0');
    // текущее смещение
    $index = ($this->offset) ? $this->offset : 0;
    //Какие-то действия, в зависимости от текущего смещения
    $start = ($this->offset) ? $this->offset + 1 : 1;
    $end = ($this->offset) ? $start + $this->block_size - 1: $this->block_size;
    $handle = fopen($this->file_path, "r");
   
   
    $row = 1;
    while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
      if($row == 1) {
        $row++;
        continue;
      }
     
     if($row >= $start and $row <= $end){
     
  $parent_id = 187; //id раздела куда будут создаваться товары
  $hierarchy = umiHierarchy::getInstance();
  $hierarchy_type_id = umiHierarchyTypesCollection::getInstance()->getTypeByName("catalog", "object")->getId();
  $hierarchy_type = umiHierarchyTypesCollection::getInstance()->getType($hierarchy_type_id);
  $object_type_id = umiObjectTypesCollection::getInstance()->getBaseType($hierarchy_type->getName(), $hierarchy_type->getExt());
        $perm = permissionsCollection::getInstance();
        $guestId= $perm->getGuestId(); // получаем id гостя
        $permLevel=1; // ставим права на просмотр всем пользователям
 
 
  $vendor = $data[0];
  $name = $data[1];

  $page_id = $hierarchy->addElement($parent_id, $hierarchy_type_id, $name, $vendor, $object_type_id);
  $perm->setElementPermissions($guestId,$page_id,$permLevel);
   
  $page = $hierarchy->getElement($page_id, true);
 
  $page->setIsActive(true);
  $page->h1 = $name;
  $page->description = $vendor; // записываем производителя в поле с именем "vendor"
 
  $page->commit();
}
      if($row > $end) break;
      $row++; 
    }
    fclose($handle);
    $this->offset += $this->block_size;

    // условие для остановки цикла, которое необходимо настроить
    if (!$data) $this->complete = true;
   
    //тестовый лог
    //file_put_contents(CURRENT_WORKING_DIR .'/traceajax.txt', $index.';', FILE_APPEND);

    return $doc;
  }

  public function translate(DomDocument $doc) {
    return $doc->saveXML();
  }
}
?>
Спасибо Admin!
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 08 Октября 2013, 23:37:32
еще бы посоветовал вытащить все общие переменные перед началом цикла, мелочь конечно, но приятная)
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 10 Октября 2013, 13:20:43
Вылетает ошибка при установке значения в поле типа Дата, в чем может быть проблема?
Пробую так:

 $page->konec_akcii = $dateend;

Предполагаю что требуется отформатировать дату, но не совсем пойму как это сделать!
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 10 Октября 2013, 13:30:09
$dateend должна быть в timestamp формате, если не ошибаюсь)
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 10 Октября 2013, 13:39:36
Да действительно в timestamp, но возникла другая проблема поле с типом Выпадающий список? Система отдает ошибку!
Получается либо создавать значение либо брать имеющееся!?
В общем с жтим вообще непонятно!!!
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 10 Октября 2013, 13:55:41
с выпадающим списком обычно все просто, отдаешь строковое значение и система пытается найти элемент с таким именем, если его нет, то создает новый
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 10 Октября 2013, 14:12:34
Я делаю просто таким способом правильно или нет?

$page->promokod = $skidka;?

Или его предварительно надо обработать?
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 10 Октября 2013, 14:54:20
вопрос прекрасен ;) особенно в виду того, что я не знаю что из себя представляет поле с именем promokod  и что за переменная $skidka
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 10 Октября 2013, 15:51:49
Да действительно не уточнил!)
В общем так:

 $skidka  = $data[16]; --- сооотв столбец из файла csv
 promokod - поля с типом - Выпадающий список!


Название: Re:Новый формат импорта CSV?
Отправлено: admin от 10 Октября 2013, 17:09:12
и еще не плохо было бы показать пример значений из столбца номер 16
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 10 Октября 2013, 17:37:12
Да значения такие:
10%
70%
40%
и тд
Те все в процентах!
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 10 Октября 2013, 18:17:27
на первый взгляд все ок, а что получается в итоге импорта?
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 10 Октября 2013, 18:22:36
Да в итоге то при включении импорта, umi отдает ошибку, проблемы записи и обновления значений в бд!
Причем, проблема возникает именно с этими полями) Хотя товары все равно создаются!

Название: Re:Новый формат импорта CSV?
Отправлено: admin от 10 Октября 2013, 19:44:23
это уже что-то нетипичное, попробуйте строчку экранировать, может там символ процента все портит
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 11 Октября 2013, 16:00:20
Почистил строку str_replace() и все ок!
Спасибо, за подсказки!
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 11 Октября 2013, 22:46:36
А вот возникла еще проблема!!!
Если я импортирую еще раз этот же csv файл, то получается что создаются новые страницы!!!
Есть столбец с id в самом файле csv, возможно ли использовать selector?
Сам попробовал не получилось страницы все равно создаются!
Не подскажите?
И второй вопрос хочу поделиться данной разработкой как мне это лучше сделать?
Название: Re:Новый формат импорта CSV?
Отправлено: admin от 11 Октября 2013, 23:06:57
По поводу первого вопроса:
Здесь лучше использовать встроенный в umi функционал, который запоминает id старого объекта, id нового объекта и тип импорта.

То есть, если вы создаете новый импорт, то можно создавать связи между id из csv и id созданного объекта\страницы в umi. И не забывать проверять при импорте, нет ли уже такой связки... если есть, то система будет обновлять уже существующий объект\страницу.

Делается это таким функционалом.

1. создание нового импорта (запускается единожды, чтобы в базе данных, соответствующей таблице появился новый тип импорта)
umiImportRelations::getInstance()->addNewSource('csv_new');

2 получения id типа импорта, по его названию
$source_id = umiImportRelations::getInstance()->getSourceId('csv_new');

3. попытка найти связку по $id из csv
$page_id = umiImportRelations::getInstance()->getNewIdRelation($source_id, $id);

4. создаем новую связку, если связка не существовала и мы создали новый объект\страницы ($id - id из csv, $element_id - id в umi)
umiImportRelations::getInstance()->setIdRelation($source_id, $id, $element_id);

По поводу второго вопроса. Лучше всего развернутая статья с примером кода, начиная от создания нового типа csv импорта, отлаживания ошибак, т.п. и заканчивая примером (csv файл, код csv splitter).

Если есть желание, пишите статью. Затем, после проверки, её можно разместить на umihelp.ru с вашим авторством.
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 13 Октября 2013, 01:16:44
Странно почему то не импортируется все записи!
И постоянно выпадает ошибка:

Cannot add or update a child row: a foreign key constraint fails (`МОЙСАЙТ`.`cms3_hierarchy`, CONSTRAINT `FK_Domain from domain_id relation` FOREIGN KEY (`domain_id`) REFERENCES `cms3_domains` (`id`) ON UPDATE CASCADE) in query: INSERT INTO cms3_hierarchy (rel, type_id, domain_id, lang_id, tpl_id, obj_id) VALUES('179', '55', '4', '1', '4', '8873')

А также еще возник как можно сделать проверку на пустое поле?
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 13 Октября 2013, 23:42:32
Разобрался сам были ошибки в коде + поставил параметр handle больше!
Название: Re:Новый формат импорта CSV?
Отправлено: muldy от 16 Октября 2013, 14:08:08
Возникла еще одна необходимость, получить заданные параметры импорта!
Те есть Тип данных - Импорт. В нем добавляю поле и соотвественно, как мне получить его в файле?
Поле например: Дата?