Как известно, для работы с CSV-Файлами PHP предоставляет функции fgetcsv и fputcsv. Поскольку эти функции обрабатывают файл построчно, то загрузка данных в базу данных происходит очень медленно: я так ни разу и не дождался, когда же обработается тестовый файл 40 метров длиной.
Опрос показал, что есть специальные средства, позволяющие загрузить CSV в базу очень быстро - речь шла о софтине bcp из комплекта MS SQL. Но тулза эта виндовая, а мне требовалось решение на кросс-платформе.
Так я обнаружл в MySQL'е наличие мега-структуры LOAD DATA IN FILE. Работает ну очень быстро: мой преславутый файл в 40 метров загружается за 16 секунд. В этом SQL-запросе есть всё, что надо для работы с CSV: указание символов для экранирования и отквочивания, пропуск первых N строк (заголовок), итд.
Кому лень ковырять мануал, милости прошу поюзать специально мной написанный для этой цели PHP-класс.
Тут вот в комментах люди отмечают, что пишу я вещи в ПРИНЦипе прозаические (про заек?), словно вынырнул я из каких-то неведомых глубин программирования и узрел свет в оконце - более простые и даже примитивные методы запрогать что-то полезное. Да, я согласен, для многих людей то, что я здесь излагаю - проза, скучная, серая. А для многих других - новинка, даже диковинка.
Но когда я вижу вот такой код, то я готов завести ещё 5 блогов и писать ещё более простые вещи ещё более примитивным языком:
<?php $idmode = $userdata->user_idmode; if ($idmode == 'nickname') $user_identity = $userdata->user_nickname; if ($idmode == 'login') $user_identity = $userdata->user_login; if ($idmode == 'firstname') $user_identity = $userdata->user_firstname; if ($idmode == 'lastname') $user_identity = $userdata->user_lastname; if ($idmode == 'namefl') $user_identity = $userdata->user_firstname. ' '.$userdata->user_lastname; if ($idmode == 'namelf') $user_identity = $userdata->user_lastname. ' '.$userdata->user_firstname; if (!$idmode) $user_identity = $userdata->user_nickname; ?>
Код я этот откопал в одном популярном блоговом движке, не буду называть его, чтобы не портить людям настроение.
Как бы я написал? Просто: switch() и в дефолте $user_identity = $userdata->user_nickname;
Кстати, знаете, как я понимаю, что написанный код действительно хорош? Когда после N-ной правки я удаляю половину кода, а функциональность не теряется и не ухудшается. Чаще всего так получается сделать, если сделегировать часть работы какой-то другой и более грамотно написанной программе: броузеру, апачу, май-эс-кью-элю, самой операционке... И тогда я слышу чей-то шепот за спиной: keep it simple, stupid :]
Я уже писал, как можно заменить связку из трёх запросов SELECT-INSERT-UPDATE на один запрос INSERT-SELECT FROM-ON DUPLICATE KEY UPDATE. Так же я тогда отметил о таком не очень удобном моменте, как необходимость нагенеривать данные для запроса: как для INSERT-блока, так и для UPDATE-блока. Например, в данный момент я ковыряю кусок кода, который либо добавляет нового подписчика, либо обновляет данные существующего:
<? $sql = "INSERT INTO `subscription` (`email`, `id_language`, `id_currency`) VALUES ('".$email."',".$language.",".$currency.") ON DUPLICATE KEY UPDATE `id_language`=".$language.", `id_currency`=".$currency; ?>
Видите? Бедному РНР нужно подставить значения переменных не только в INSERT, но и в UPDATE. Чем это плохо? Во-первых, если придётся ковырять этот код в следующий раз, например, перед значениями $language и $currency приписать (int), чтобы явно привести их к целому типу, то придётся сделать 4 правки. Во-вторых, работы для PHP-сервера больше: одно дело просто строчку скопировать, другое - проставлять значения переменных. Столбцов может быть не 2-3, а 20, да плюс несколько таких запросов (в цикле) - тогда это может быть значительно.
Чтобы в этой ситуации облегчить работу PHP-серверу и немного больше напрячь ленивый SQL-сервер, есть функция VALUES(). Она позволяет, в данном случае, обратиться в UPDATE-блоке к данным из INSERT-блока. Таким образом, код становится чище:
<? $sql = "INSERT INTO `subscription` (`email`, `id_language`, `id_currency`) VALUES ('".$email."',".$language.",".$currency.") ON DUPLICATE KEY UPDATE `id_language`=VALUES(`id_language`), `id_currency`=VALUES(`id_currency`)"; ?>
Я давно хотел обучиться скорочтению, дабы повысить свою производительность. Как-то в Москве я купил книгу на эту тему, и одним из главных и самых длительных упражнений в ней является чтения узкой колонки текста с захватом глазом всей строки целиком; со временем ширина колонки должна увеличиваться, и в итоге таким образом можно читать всю строку в обычной книге целиком.
Меня долго смущала практическая реализизация такого требования: где найти много текста разной ширины. Я сразу откинул идею скачивания с lib.ru разных книжек и переформатирования их в броузере или ворде - читать с экрана не люблю, только по необходимости.
И вот сегодня меня осенило! Я читаю блоги в Абилоне, и одна из вертикальных колонок в его окне служит для отображения текста конкретного заголовка: разумеется, ширина этой колонки регулируется, таким образом обеспечивая удобный интерфейс для 1) моего обучения и 2) чтения новостей. Всё равно такую информацию я на бумаге не читаю...
Таким образом, я получаю выгоду от чтения интересных новостей :]
Идея, описанная ниже, родилась в таких условиях: у меня постоянно невовремя кончалась предоплата за инет в нашей районной локалке, но через бесплатную местную проксю продолжала работать аська (ICQ); тогда я подумал, что чисто технически было бы интересно реализовать такую систему халявного (для меня) интернета:
я пишу адрес (УРЛ) в броузере. В настройках броузера прокси-сервер прописан как локальный адрес, который на самом деле представляет собой плагин к миранде, благо она предоставляет интерфейс для плагинов. Таким образом адрес попадает в аську;
плагин в миранде коннектится к серверу ICQ через бесплатный местный прокси-сервер и после этого остылает принятый УРЛ на определённый ICQ-номер (задаётся в настройках). Таким образом адрес попадает на другой номер;
другой номер - это мой PHP-скрипт на удалённом серваке, который крутится в цикле и принимает входящие ICQ-сообщения (типа демон);
получив адрес, PHP-скрипт делает читает весь контент по этому адресу и возвращает его обратно по цепочке в мой броузер.
Думаю, схема будет работать даже для всяких имеющихся на странице картинок, скриптов и цсс-файлов.
На данный момент меня смущает только пункт 1: не знаю, как это грамотно сделать, всё руки не доходят попробовать...
Тырить инет - очень по-русски, но меня интересует только техническая сторона :]
Оказывается, люди очень похожи - уже в который раз я слышу от разных товарищей то же, что раньше говорил сам: Punto Switcher (далее ПС) неудобен, потому что лезет исправлять то, что не нужно. Ну что ж, так и есть, если он работает в автоматическом режиме. Я подумал, что неплохо будет поделиться своим опытом, потому что ПС - удобный молоток для забивания сразу нескольких гвоздей.
Итак, первое, что я делаю после инсталляции, это выключаю автоматический режим и звуки. Таким образом, я и только я руковожу процессом корректировки текста, а также берегу сон своих близких.
С этого момента в ваших руках появляются следующие шоткаты, к которым привыкаешь достаточно быстро:
Break - конвертировать раскладку (если вы набрали "cfif", то это тут же по нажатии Break превратиться в "саша"). Отлично работает для только что набранного слова;
Shift+Break - конвертировать раскладку для всего выделенного куска текста.
Alt+Break - инверсия регистра (было "Саша", выделяем, нажимаем, становится "сАША");
Alt+ScrollLock - перевод в транслит: соответственно, только из русского в английский (было "Саша", выделяем, нажимаем, становится "Sasha"). Из-за включённого таким образом ScrollLock может неожиданно странно начать себя вести скроллинг с клавиатуры в Excel, но это поправимо - выключите его и всё (ScrollLock, не Excel :] ).
Это раз.
Есть такая удобная штука, как автозамена. Сие означает, что набор всех часто набираемых комбинаций текста можно упростить. Какой текст программиста чаще всего набирает? Вот мои примеры:
for($i=0; $i>sizeof($data); $i++)
while(list($key, $val) = each($attributes))
not_empty_array()
$attributes[""]
border: 1px solid blue;
document.getElementById('')
ну иногда ещё своё имя или фамилия в письмах
Всё это я получаю, набрав первые 2-3 буквы, после чего загорается виндосовский хинт, сигнализирующий о том, что если я нажму пробел, мой текст будет автоматически заменён.
Чтобы получить такое мега-подспорье, заходим в Параметры -> Автозамена и набиваем все нужные комбинации в последний раз :] Рекомендую клавишей замены назначить пробел, а не таб или ентер - мне кажется, так удобнее.
Хинт: не надо набивать в поле "Заменять что" нормальных слов типа "for" или "while" - это чревато тем, что вы будете материться, когда в письме напишете это слово, затем нажмёте естесственный пробел, а этот "глупый ПС" сделает замену! Лучше использовать "fo" и "whil".
Это два.
И теперь три: на закуску супер-мега тул. Называется "история буфера обмена", выглядит обычным поп-ап меню так:
С помощью этой приблуды я могу накопировать в буфер разные нужные куски кода в одном месте программы, а потом повставлять их в другом.
Вызывается по настраиваемому шоткату. Правда, есть какое-то накопительное ограничение на длину текста, и тогда ПС просто перестаёт запоминать новые куски, но такое наблюдается после нескольких дней хибернейчения (вы ещё не хибернейтите? Тогда мы идём квам-квам), а не при нормальном выключении компа после работы.
Как настроить.
Идём в Параметры -> Общий и включаем галку "Разрешить слежение за буфером обмена".
Шагаем в Параметры -> Горячие клавиши, там выбираем пункт "Показать историю буфера обмена", и выставляем шоткат (у меня это англ. буква H + клавиша Win).
В ПС есть ещё несколько функций, но ими не пользуюсь. Если кто научит - спасибо скажу.
Когда нужно проверить несколько числовых значений, превышают ли всеони нуль (важные значения, однако!), то можно их просто перемножить и проверить результат:
if($id_product * $id_boutique * $id_top > 0)
Примерно так же можно проверить, является ли хоть одна из проверяемых строк непустой:
JSMin - это маленькая консольная прожка (33 Кб), которая получает на вход код JavaScript, а на выходе выдаёт код JavaScript с выкушенными комментами и переносами строк. Код остаётся работоспособен и не принимает вид одной строки - я так думаю, потому, что в JavaScript концом оператора может считаться как точка с запятой, так и конец строки, а в последнем случае слепить две строки означает нарушить работоспособность программы. Так что ваш код принимает просто менее документированный вид, типа продакшн-сурс.
Как пускать. Внимательный читатель, думаю, заметил, что я написал "получает на вход код JavaScript" - сие означает, что надо передать параметром не имя файла, а его текст. В простейшем случае - запустить jsmin.exe и набить всё вручную в консоли. Но мы же украинские девелоперы! Да здравствует автоматизация!
Такой командой мы передаём этому выкусывателю текст входного файла, и указываем, куда сложить вывод: