Скрипт предназначен для обновления остатков по торговым точкам, ну и заодно цен розничных и в интернет-магазине, из базы 1С. Данные передаются через промежуточный файл .csv.
Скрипт укладывается по времени в 1-2 секунды. То есть остатки можно синхронизировать хоть каждую минуту. К сожалению 1С не может похвастаться таким же быстродействием...
Сам скрипт:
<?php
header('Content-Type: text/html; charset=utf8');
mb_internal_encoding("UTF-8"); // Установка внутренней кодировки скрипта UTF-8
setlocale(LC_ALL, "ru_RU.UTF-8");
if(isset($_GET['DEBUG'])) define('DEBUG', true);
else define('DEBUG', false);
// Конфиг
$allow_col_num = 9; // Количество колонок во входном файле
$path = dirname(__file__).'/';
$file_input = '/home/domain.ru/www/1c_import.csv'; // Этот файл генерируется скриптом в самой 1C
$file_buffer = 'buffer.csv';
$file_errorlog = 'errors.csv';
$file_refresh['spb'] = 'refresh.spb.dat';
$tablename['spb'] = 'import_temp_spb';
require_once $path.'pdo.config.php'; // Подключение конфига БД
extract($dbconfig);
$prefix = 'modx_'; // Префикс таблиц ".$prefix."
// Инициализация
define('MODX_API_MODE', true); // API MODX
require_once $_SERVER['DOCUMENT_ROOT'].'/index.php'; // MODX
$modx->getService('error','error.modError');
$modx->setLogLevel(modX::LOG_LEVEL_INFO);
$modx->setLogTarget(XPDO_CLI_MODE ? 'ECHO' : 'HTML');
$arr=file($file_input);
$count=0;
// Функции
function logWrite($str, $fh=null)
{
if(DEBUG) print "log: $str\n";
// TODO: Запись в errorlog
}
if(DEBUG) print "\n";
// ОТКРЫТИЕ buffer.csv
// -------------------------------------------------------\
$fhBuf = fopen($path.$file_buffer, "w");
ftruncate($fhBuf, 0); // очищаем файл до 0 байтов.
$locked = flock($fhBuf, LOCK_EX | LOCK_NB);
if(!$locked) {
echo 'Не удалось получить блокировку';
exit(-1);
}
logWrite(date('j-m-Y H:i:s'));
logWrite('Чтение файла 1c_import.csv');
foreach($arr as $str)
{
$fields=explode(';',$str);
$num=count($fields);
if($fields[1]=='Артикул') {logWrite("Строка заголовков удалена"); continue;}
if($num!=$allow_col_num) {logWrite($str); continue;}
$count++;
fwrite($fhBuf, "$str");
}
$output = "Запись в буфер: ".$count." строк к импорту";
logWrite($output);
// ЗАКРЫТИЕ buffer.csv
fflush($fhBuf) or die($php_errormsg);
flock($fhBuf,LOCK_UN) or die($php_errormsg);
fclose($fhBuf) or die($php_errormsg);
unset($fhBuf);
/**/
// ---------------------------------------------------/
// Подключаемся к БД
try {
$db = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass, array(
PDO::ATTR_PERSISTENT => true,
PDO::MYSQL_ATTR_LOCAL_INFILE => true
));
} catch (PDOException $e) {
logWrite('Подключение к БД не удалось: '.$e->getMessage());
exit(13);
}
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec("set names utf8");
// ------------ Импорт buffer.csv -> БД ------------------------
$db->exec("TRUNCATE TABLE `import_temp_raw`;");
$res=$db->exec("LOAD DATA LOCAL
INFILE '".$path."buffer.csv' INTO TABLE `import_temp_raw`
fields terminated by ';'
enclosed by ''
lines terminated by '\n';");
logWrite('Результат импорта в БД: '.$res.' строк внесено');
/**/
//------------- САНКТ-ПЕТЕРБУРГ -----------------------------------------------------------------------\
// Генерируем временную таблицу по Питеру
$sql="CREATE TEMPORARY TABLE IF NOT EXISTS temp_import_spb AS (
SELECT `id`,`article`,`name`,`vendor`,`weight`,
SUBSTRING_INDEX( `supply` , '=', -1 ) AS `quantity`,
SUBSTRING_INDEX( `price` , '=', -1 ) AS `price`,
SUBSTRING_INDEX( `old_price` , '=', -1 ) AS `old_price`
FROM `import_temp_raw`
ORDER BY `article` ASC
)";
$res=$db->exec($sql);
logWrite('Сборка временной таблицы по СПб: '.$res.' строк внесено');
// Составляем список ресурсов с изменениями
$sql="SELECT m.id
FROM `".$prefix."ms2_products` as m, temp_import_spb as t
WHERE m.article=t.article
AND (m.quantity<>t.quantity
OR m.weight<>t.weight
OR m.price<>t.price
OR m.old_price<>t.old_price)
ORDER BY `id` ASC";
$stmt=$db->query($sql);
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$refreshIDs=array();
while($res = $stmt->fetch())
{
$refreshIDs[$res['id']]='';
}
//print_r($refreshIDs);
logWrite("Изменения обнаружены в: ".count($refreshIDs)." товарах");
// TODO: Сохраняем сериализованный массив ресурсов с изменениями в файл refresh.spb.dat
// А может и не надо...
// Заливаем новые данные в рабочую таблицу ms_products
$sql="UPDATE `".$prefix."ms2_products` as m, temp_import_spb as t, `".$prefix."site_content` as c
SET m.quantity=t.quantity,
m.weight=t.weight,
m.price=t.price,
m.old_price=t.old_price
WHERE m.article=t.article
AND m.id=c.id
AND c.context_key='web'";
$res=$db->exec($sql);
logWrite('Запись новых данных: '.$res.' строк внесено');
/**/
//------------- САНКТ-ПЕТЕРБУРГ ВЫПОЛНЕНО ---------------------------------------------------------------------/
// Избирательная чистка Кэша
//print_r($refreshIDs);
foreach($refreshIDs as $id => $val)
{
//$id=79;
$resource=$modx->getObject('modResource',$id);
$cacheKey = $resource->getCacheKey();
$modx->cacheManager->refresh(array(
'resource' => array('key' => $cacheKey),
));
}
// Финиш
logWrite('затраченное время: '.(microtime(true) - $modx->startTime));
logWrite('');
if(DEBUG) print "";
в скрипте подключается файл с доступами к БД pdo.config.php вида:
$dbconfig[dbhost] = 'localhost'; $dbconfig[dbuser] = 'ваш_логин'; $dbconfig[dbpass] = 'ваш_пароль'; $dbconfig[dbname] = 'имя_базы';
Cтруктура временной таблицы:

Результат выходит следующий:
log: 28-03-2014 14:01:34 log: Чтение файла 1c_import.csv log: Строка заголовков удалена log: Запись в буфер: 755 строк к импорту log: Результат импорта в БД: 755 строк внесено log: Сборка временной таблицы по СПб: 755 строк внесено log: Изменения обнаружены в: 1 товарах log: Запись новых данных: 0 строк внесено log: затраченное время: 0.68212199211121 log: