Показаны сообщения с ярлыком php. Показать все сообщения
Показаны сообщения с ярлыком php. Показать все сообщения

вторник, мая 21, 2019

Жаркий день в аду

ИЛИ

Самый прикольный на этот день проект в моей жизни - система управления производством и заказами - состоит из пяти серверов в двух городах и проектировалась децентрализованной: серверы могут общаться, но отключение связи в любой точке не останавливает её работы: часть функций отпадает, основные действуют.

В каждом сервере торчит флешка, на которую еженощно бэкапится база данных.

Был один зияющий пробел, который меня беспокоил: однажды в одной из точек вылетит сервер. Это неизбежно случится. Что я буду делать?



К счастью, один из серверов чудовищно избыточен (настоящий, стоечный) и наименее загружен. Что если заготовить там работоспособные копии всех остальных систем и держать актуальные копии баз?

automysqlbackup создаёт бэкап базы в каталоге latest (при включенной опции latest), это хардлинк на последний файл в каталоге daily. Файл содержит в имени дату. Это неудобно, его надо переименовать (это значит, что файловая система должна поддерживать хардлинки, поэтому бэкапные флешки отформатированы в ext4).

Алгоритм:

1) монтируем флешку (на случай, если не);

2) бэкапим базу;

3) если удачно, удаляем daily.sql.qz в latest

4) переименовываем дамп базы в daily.sql.qz (в старых версиях дамп начинается с имени базы, в новых - с daily; соответственно, переименовываем файл, начинающийся на p или на d);

5) чмодим daily.sql.qz для чтения всеми (новая версия automysqlbackup создаёт его rw----).

Для этого создаём /root/backup с содержимым:

#!/bin/bash
mount /dev/sdb1 /mnt/backupflash; /usr/sbin/automysqlbackup && rm /mnt/backupflash/sql/latest/daily.sql.qz; mv $(ls /mnt/backupflash/sql/latest/p*) /mnt/backupflash/sql/latest/daily.sql.qz && chmod a+r /mnt/backupflash/sql/latest/daily.sql.qz

Выделено жирным: 1) automysqlbackup старых версий находится в /usr/local/bin, новых - в /usr/sbin; сделать whereis automysqlbackup от рута, чтобы узнать. 2) см. разницу p/d выше.

Делаем исполняемым chmod +x /root/backup и ставим в крон рута на ночное время.

0 3 * * * /root/backup >/dev/null 2>&1

Теперь на принимающей стороне. Здесь мы обходимся rsync в crontab:

0 7 * * * sshpass -p "PASSWORD" rsync LOGIN@HOST:/mnt/backupflash/sql/latest/daily.sql.gz /SOMEWHERE/HOST/ >/dev/null 2>&1

Чтобы это работало, надо предварительно соединиться по ssh с источником, чтобы сохранился ключ соединения. rsync должен иметься на обеих сторонах, конечно.

И копия рабочей системы:

5 7 * * * sshpass -p "PASSWORD" rsync -az LOGIN@HOST:/SOMEPATH /var/www/HOST >/dev/null 2>&1 

И резервные базы-то обновить, опустим подробности, это zcat и mysqladmin нужных файлов в нужные базы (их надо сперва создать).

Базы должны иметь различные между собой названия и такие же реквизиты доступа, как на оригинальных системах.

Дальше нам надо создать виртуальные серверы для каждой системы, я их делал на основе ip-адреса.

Я более-менее закончил с этим в понедельник вечером (нет предела совершенству: в идеале переключение между основной и резервной системой должно делаться в настройках центрального сервера - не успел).

Во вторник с утра вылетает один из серверов во Владивостоке.

Сука, едва успел пригнуться, а то бы убило.

Точка весь день работала на созданной накануне резервной системе. Если бы резерва не было, денежные потери потребовали бы для записи MEDIUMINT.

воскресенье, октября 22, 2017

Программируемый калькулятор: мой первый плагин WordPress



Задача: расставить на страницах сайта калькуляторы расчёта стоимости потолка, балкона, окна, кондиционирования.

Параметры должны быть настраиваемыми.

Сайт на WordPress. Соответственно, настройка в админке.

Яваскриптить четыре калькулятора было в лом, поэтому от себя добавил условие: один универсальный скрипт на все калькуляторы, расчёты программируются параметрами полей ввода.

Загуглил, как устроен плагин WP (и сам WP заодно). На Хабре хорошие примеры. Немного поковырял, получил страницу в админке.

Сохранять и получать массив параметров удобно через вордпрессовские  get_option() / update_option().

Вставлять калькулятор в страницу - через shortcode с параметром.

Перешёл к самому интересному: скриптингу расчётов.

Всё, что участвует в расчёте, обозначим классом factor.

Калькуляторы не отнимают и не делят. Только два действия. Соответственно, нужны поля двух классов: add и mul. Первое прибавляет к итогу, второе - умножает итог.

При событиях change, keyup со всем, имеющим класс factor, вызывается пересчёт.

Со сложением всё просто, а с умножением пришлось писать варианты. Если функции умножения передаётся один параметр, умножаем итог на него. Если два - перемножаем их и прибавляем к итогу.

Когда уже всё казалось красивым, возникла проблема:  как быть с набором опций, каждая из которых прибавляет процент к итогу? Калькулятор считает поле за полем,  итог будет расти, процент тоже.

Покрутил так и эдак, пришёл к схеме: если среди $('.factor') есть что-то с классом freeze, запомнить итог на этот момент. Если дальше что-то имеет класс use-frozen, оперировать не итогом, а его замороженным значением.

Всё гениальное frozen.

Заодно добавим класс cm2m, значения этих полей при пересчёте переводим из сантиметров в метры на лету.

Получился универсальный калькуляторокомплект. Что угодно для несложного расчёта с суммированием и коэффициентами сооружается буквально за несколько минут.

Если это хорошо упаковать (встроенный редактор калькуляторов, шаблоны внешнего вида, адаптив, i18n), годится как самостоятельный товар.

понедельник, августа 08, 2016

Ушёл на базу. Через шифрованную дырку.

С открытием второй пиццерии (с моей точки зрения - с развёртыванием второй системы управления производством) возникли вопросы взаимодействия:

Как дать возможность оператору отправить заказ на нужную пиццерию?

Как формировать консолидированные отчёты по двум точкам?

Как синхронизировать меню, цены, акции, дисконты, купоны - всё, что может измениться в любой момент?

Вариант master/slave в MySQL сразу не рассматривал, потому что схема должна быть такой, чтобы пережить атомную бомбардировку: уцелевшие пиццерии должны продолжить автономную работу несмотря на оборванные провода и исчезнувшие соединения.

Это можно сделать через REST: куча писанины и куча новых ошибок.

Либо обращаться к базе удалённо.

Пару дней обдумывал это. Второй вариант позволял максимально использовать уже написанный код. Но не хотелось создавать новых сетевых дырдочек, в которых так увлекательно колупаться фомкой.

Немножко почитал интернеты и понял, что понадобится:

autossh - надстройка над ssh, поддерживающая соединение в рабочем состоянии, пока это возможно;


И всё.

К слову, Гугл по поиску autossh в третьей позиции даёт ветку под названием "Чтоб вы знали: autossh - полное дерьмо". Я её внимательно изучил. Она меня не убедила.

Ещё нужен скрипт для управления autossh как службой, он находится здесь и отлично встраивается в Debian.

Смотав это всё синей изолентой, получаем на сервере А новый порт MySQL, открытый в тьму внешн базу данных сервера Б, без создания новых дырок, через зашифрованное, автоматически устанавливающееся и магически восстанавливающееся соединение.

Дальше - с отвёрткой в зубах - в PHP-класс работы с SQL. Здесь делаем выбор параметров соединения из массива предопределённых вариантов. Важно: если сервером указывать localhost, запрос такого-то порта будет проигнорирован. Поэтому указываем 127.0.0.1. Вроде хрен и редька, а вот хрен.

Настало время первой проверки. Пишем коротенький скрипт, который запрашивает максимальные идентификаторы из таблиц заказов серверов, разнесённых на некоторое количество километров:

Холишыт, это действительно работает!

Дальше так: в интерфейс операторов, принимающих заказы с доставкой, добавляем выбор пиццерии:


Чуть позже по умолчанию будет та, чей этот клиент географически.

И теперь, если запрошена недефолтная пиццерия, просто пересоздаём класс базы данных с указанием другого соединения, и наш старый код пишет заказ в таблицы нужной пиццерии.

Дальше надо поэкспериментировать и понять, как лучше строить консолидированные отчёты: federated table?

Ну и автоматические обновление настроечных данных: надо переписать методы класса работы с БД, чтобы запросы можно было автоматически проигрывать на выбранном или всех доступных соединениях.

вторник, июля 19, 2016

Чековый принтер Posiflex AURA 6900 + Linux

Более двух лет назад пришлось подключать чековые принтеры Posiflex 6900 к производственной системе, построенной на LAMP. Тогда я решил эту задачу минималистично: обнаружил, что принтер тупо выводит на ленту всё, что приходит на порт TCP 9100 (обнаружил случайно: попытался открыть порт 9100 браузером и увидел на ленте заголовки HTTP-запроса). Русские буквы выходили двухбайтными; установить, что встроенный шрифт использует codepage 866, было просто. Написал вывод текстовых чеков на порты нужных принтеров, и больше двух лет так и работало.

Сейчас возникло желание поиметь красивые чеки с картинками и шлюхами. Для этого надо подключить принтер через CUPS. Исследование инета показало. что: 1) драйверов для CUPS нет ни у производителя, ни у вендоров; 2) в инете есть 2 (две) релевантные темы на форумах, ни в одной нет решения. Но! В одной из тем топикстартер приложил файл 6800.zip. Внутри обнаружился PPD для этого типа принтеров и - бааааа! - файл rastertopp7, который, ясное дело, представляет собой принтер-специфический фильтр CUPS. Файл оказался 32-bit ELF binary. Система 64-битная. Хьюстон, у нас тово.

Положил фильтр в /usr/lib/cups/filter. Добавил принтер, подключение: socket://xxx.xxx.xxx.xxx:9100, скормил найденный PPD. Попробовал напечатать тестовую страницу, получил сообщение "Filter failed". Естественно: рыба-то пресноводная, а водоём-от солёный.

Я поискал исходники и почти нашёл. На тайваньском сервере. С китайским интерфейсом. За скачивание попросили 50 юаней. Я пожопился из-за отчётливого ощущения разводилова. Адрес пользователя, разместившего архив, был в mail.ru.

Остался план Б: мультиархитектура. Добавил архитектуру i386 в систему:

dpkg --add-architecture i386

добавил 32-битные библиотеки:

apt-get update

apt-get install ia32-libs

Повторил пробную печать. Filter failed. Недодавил где-то.

ldd /usr/lib/cups/filter/rastertopp7 | grep found

Выхватил сообщение о не найденной libcupsimage.so.2

apt-get install libcupsimage2:i386

Повторил печать. Из принтера вылезла пробная страница с пингвином.

Теперь всё просто:  1) чек рисуется в HTML; 2) пропускается через mPDF, получается PDF; 3) отправляем его на принтер, ждём несколько секунд и удаляем файл. Несколько уродски, но просто и работает, а простые фокусы - самые надёжные.




среда, февраля 12, 2014

Сказ о том, как платёжная система с хостингом не подружилась

Злободневное, и может сэкономить кому-то время и мозг.

Подключал платёжную систему PayAnyWay (Монета.Ру) к сайту на Фабрике Хостинга (hostfabrica.ru). Всё нормально, но не доставляется техническое уведомление о прохождении платежа. Оно происходит невидимо для пользователя. Пользователь получает своё спасибо, деньги поступают, но на технический е-мейл начинают десятками идти сообщения от Монеты.Ру о невозможности передать уведомление.

Техподдержка Монеты.Ру поясняет, что их сервер по адресу Pay URL получает 403.

Делаю запрос из браузера руками: всё работает.

Техподдержка Фабрики Хостинга предполагает, что Монета.Ру не передаёт user-agent, и такие запросы получают 403.

Монета.Ру отвечает, что user-agent передаётся.

Круг замкнулся, мои возможности были исчерпаны.

Можно было попробовать ввести их в диалог друг с другом, но - время. Поэтому просто перевёл сайт на другую площадку (hostline.ru). Всё работает.

Итоги:

1) если непонятно не работает уведомление на Pay URL от Монеты.Ру, причина может быть в блокировании их робота хостером.

2) до решения этой проблемы сайты с подключенной Монетой.Ру не будут полноценно работать на Фабрике Хостинга. Вряд ли их конфигурация в этом уникальна. То есть нестыковка может происходить и на других площадках.

понедельник, мая 28, 2012

Оопнулся

Сегодня, приступая к глобальному переписыванию одного из больших PHP-проектов, заставил-таки себя перейти на объектно-ориентированный код. XIX век уже практически на исходе, а я до сих пор обходился функциями.

Не то чтобы очень надо, но эта тёмная туманность на периферии зрения изрядно раздражала. Надо её прояснять.

Для начала переписал свою SQL-библиотечку в виде класса, и практически после пары ошибок она взяла, да и заработала.

Но это была задачка хрестоматийная, а сейчас надо будет описывать в виде классов проекты и документы.

Просто слишком муторно делать это старым способом, нормальный бардак в коде неуклонно превращается в непостигаемый хаос.

Звонил сосед по парте даче, у него сегодня пакет крабьей икры. А я заслужил своё вечернее пиво.

среда, февраля 29, 2012

Ну и продолжаем прибывать русский интернет

Сайт фитнес-центра F-City был открыт недели две назад, как-то просуетил этот момент. Проект рекламного агентства Brand-PR. Я ранее выкладывал (довольно стрёмные) наброски по этому сайту.


Для подшивки.

вторник, декабря 14, 2010

Bridge Logistics: теперь с новым корейским вкусом

Впервые опробовал свою надстройку для многоязыковых сайтов в реальной жизни на неевропейском языке. Как ни странно, работает. Почти гладко. Есть куда развивать, конечно.



http://bridgelogistics.ru/

четверг, мая 06, 2010

GT-Клуб Находка: запущен



Запущен, активно бетится. Грядут изменения и доработки.

Из исторического:

1) первое настоящее, полноформатное применение своего магазина, и
2) форум, также домашней выпечки (по ряду причин). Форум ждут не дождутся ещё два других сайта.

Вчера была первая покупка: заказали кое-что аж из СПб.

четверг, февраля 25, 2010

i18n на свой лад: пока без комментариев... почти

Адским усилием мысли в общем осилил pluggable систему поддержки интернационализации сайта на произвольном количестве языков с полным on-screen редактированием.

Сильно устал и уже поздно, поэтому подробности позже.

понедельник, июля 27, 2009

Чья коробка толще

Взявшись за несложный вроде бы сайт, столкнулся с нестандартной задачей: на сайте галереи картинок, которые надо показывать в плавающем окне, затеняя основной контент. Что же тут сложного? Я тоже так подумал и прикрутил Thickbox, лучший, на мой вкус, плагин jQuery для просмотра картинок. Оказалось, всё не так просто. Оказалось, в плавающем окне должна быть вся галерея, и просмотр выбранной картинки тоже.

Вздохнул и сел ковырять код Thickbox. Написал свои функции, вызывая из Thickbox кое-что подручное типа определения размера окна и кое-какие определения CSS. Приходит следующая установка: ан нет, окно просмотра должно быть фиксированного размера, и всё внутри зафиксировано тоже. Плюнул, переписал вчистую. В итоге всё как надо и даже лучше (на бонус приделал просмотр картинки в полном размере), но от Thickbox в итоге осталось только... описание CSS для эффекта затенения фонового контента.



Пиши я сразу с нуля — сэкономил бы несколько часов и бутылку крови. Я думал, я был дотошен в расспросах о деталях задачи. Оказывается, нужно быть не дотошным, а изнурительно нудным: оно окупится.

Да ладно, сделал — и сделал. А всё-таки настоящий Thickbox мне нравится в сто раз больше сегодняшнего кода.

воскресенье, июля 26, 2009

Open Flash Chart

...А ещё если бы кто меня спросил: Сергей, какую библиотеку вы посоветуете для быстрого втыкания flash-графиков на сайт? — Я бы ответил: не повторяйте мою ошибку, не покупайтесь на XML/SWF Charts, хотя они и чАртовски красивы (вы зашибётесь генерировать XML для всей этой красоты, а РНР-интерфейса у этой штуки нет; я даже стал писать свой псевдоинтерфейс, да быстро прогнал наваждение). Берите Open Flash Chart: open source, интерфейс для PHP и всяких ненужных языков, а главное — нормальный объект, который нужно только пнуть раза три — и вот он, график.

четверг, июля 23, 2009

Снова про PHP и велосипед

Буду краток: PHP Thumb. Всё, чтобы получить любые thumbnails двумя-тремя строчками кода.

PHP DataGrid: ну ё-моё

Набрёл в инете на универсальное решение по работе с табличными данными: PHP DataGrid. С досады озвучил заголовок. Буквально в прошлом месяце по неведению изобрёл велосипед... ну ладно, велосипедик, трёхколёсный такой:



Табличка сервиса и есть мой аналог DataGrid с автоматической генерацией заголовков и режимов сортировки (в этом трёхколёсность: DataGrid ещё и строит запросы, и управляет данными).

Подумал... решил оставить. Во-первых, труда жалко. Во-вторых, построение более-менее сложного запроса в DataGrid — процесс многословный, а главное — трудноохватываемый глазом; в моих функциях извлечения-сохранения данных всё гораздо более очевидно. В общем, Мерседес — это хорошо, но иногда Марч уместнее. И главное: в своих функциях я знаю все входы-выходы и могу шить там любыми нитками. А просто на доскональное изучение DataGrid надо потратить много часов.

Однако, надо как-то своё велосипедное КБ прикрывать. Все наши проблемы чаще всего уже решены, надо почаще вспоминать эту истину.

пятница, июля 10, 2009

Выбираю библиотеку для работы с картами Гугла

Хотя я и собрал в общих чертах гугл-карту для грядущего сайта Прим-Поиска, работать непосредственно с Google Maps API мне не понравилось: кустарщина какая-то, ассемблер наколенный. То есть оно интересно и развивающе, но мне надо максимально просто генерить карты самых разнообразных видов из готовых наборов данных, и поменьше писать руками при этом (ведь это придётся и не раз переписывать!).

Просмотрев Freshmeat, выбрал три РНР-класса, способных решить задачу.

Один тут же отбросил из-за того, что сайт не обновлялся 2 года, а документация API 404 Not Found.

Остались два. Сижу чешу репу.

Google Maps plug-in for Word Press бразильца Ави Алкалая настолько прост в работе, что сгодится и ребёнку. Может использоваться и без Ворд Пресса. Всё, что надо, — создать HTML-список определений (definition list), где указаны параметры карты, маркеры и прочая. Остальное происходит через очень сильное колдунство.

Минусы. Сам автор признаётся, что в Invalid Explorer результат непредсказуем. Во-вторых, смутное ощущение, что колдунство довольно строго связывает в возможностях. Хотя чертовски просто и красиво всё выглядит... в теории.

GMapper Филиппа Крижки (или как прочесть по-немецки Kriszka?) — РНР-класс в чистом виде, без смутных колдунств. Создаёшь объект карты, затем скармливаешь ему данные через соответствующие методы. Жрёт XML и KML, от простейших перечислений точек до полилайнов, собственных маркеров, инфоокон с закладками. Отдельное внимание к майкрософтовскому пространству имён:
xmlns:v="urn:schemas-microsoft-com:vml"
что и составляет, подозреваю, камень преткновения предыдущего варианта.

Минусы: всё на немецком: сайт, туториалы. В принципе, не так страшно.

Пока больше глянется GMapper.

вторник, декабря 02, 2008

Златая сеть на вебе том

Сайт ювелирной сети «Злата» спускается на воду сегодня.



Когда-то я, попробовав пару-тройку готовых CMS, пришёл к шуточному заключению, что настоящая, правильная CMS — та, которую сделал сам, остальное — более или менее неудачные компромиссы. Сейчас, со сдачей «Златы», вижу, что комбинация приёмов, шаблонов и сторонних готовых инструментов, которую я применял и выстраивал на нескольких последних проектах, становится всё больше похожей если не на CMS, то на среду быстрой разработки точно.

По-прежнему требуется приличный объём ручной писанины при работе с базой данных. Но это и правильно — писать работу с базой руками. Не бывает двух одинаковых баз, а работать с ними надо оптимально. Это не слишком сложно, когда запросы к базе давно описаны функциями высокого уровня, а теперь ещё добавились такие же простые функции форматированного вывода результатов. В большинстве случаев обращения к базе выглядят как два вызова: запросить данные, вывести результат; если принести в жертву удобочитаемость кода, то можно делать и один вызов.

четверг, октября 23, 2008

База данных без базы данных

На сайт с самопальным хостингом (эх...), под Вендой (эх!...) и без MySQL (эх, мля!!!) потребовалось вставить ни много ни мало, а базу данных по автомобилям. С полями, фото и всеми делами.

Решил так. Сделаю за день — быть базе. Не сделаю — может, и быть, но не через меня.

Взялся за клаву... ну не писать же всё хранение информации в файловой системе. Пошёл в Гугл, набрал php flat file database.

Выбирал из нескольких вариантов, включая встроенный в PHP SimpleXML. Выбрал самый простой и не ошибся: Flatfile. Задачу уже решил, база работает. Всё барахло хранится в 2 крошечных файлах PHP, ноль настройки (только указать каталог, где можно писать файлы), поддерживается отдалённое (но достаточное для тривиальной работы) подобие SQL, а главное — в отличие от некоторых других аналогичных штуковин, эта не только читает файлы, но и пишет их, полностью избавляя от контакта с файловой системой и проч. Как и полагается базе.

Остаётся открытым вопрос производительности, но едва ли он будет актуальным в этом конкретном случае.

среда, апреля 23, 2008

PHP: первое использование сокета - это почти как первый поцелуй

Для сайта с каталогом недвижимости потребовалось написать разборщик удалённых файлов (веб-страниц). Тривиальная задача, но споткнулась о проблемы с открытием этих самых страниц. Стандартный способ через fopen() не работал. Через функции curl - то же самое. Масса других сайтов работает, но конкретный нужный - неа. Дошёл до того, что пошёл в удалённый порт 80 телнетом, изобразил примитивный HTTP-сеанс... и всё получил. Так какого чёрта.

Дальше просто описал в PHP то, что сделал руками: открывается сокет на $host, кричится в него:

GET $page HTTP/1.1
Host: $host
Connection: Close

...и подставляй ведро - пошли данные.

Тайна, оставшаяся тайной: если этот низкоуровневый способ работает, почему не работают fopen и curl? Одна догадка: проблемный хост генерит страницы тоже в PHP... при чтении страницы через сокет явно ощущается тайм-аут, после которого мой скрипт переходит к разборке данных... может быть, дело в незакрытом удалённым хостом соединении, из-за которого цивилизованное чтение обламывается с ошибкой, а моя дикарская функция возвращает-таки свой буфер? Не знаю, наблюдение за сеансом через Firebug не дало каких-то фактов в пользу этого, а вникать глубже мне лень и некогда, т. к. с этим разборщиком я уже стремительно приближаюсь к собственному тайм-ауту...

В общем, так: если не работают ни fopen(), ни функции curl, ни их имитация (есть примеры в инете) средствами того же fopen - простой fsockopen() может открыть дырку в заборе.

А про поцелуй... всегда считал, что кулхацкеров отличают от обычных людей два умения: написать что угодно на шелл-скрипте и работать через сетевые сокеты. Оказывается, про сокеты я был не прав... шелл-скрипты горааааздо мудрёнее, чесслово... :-)

четверг, марта 27, 2008

If you want something done... do it yourself.

Жан-Батист Эммануил Зорг



Фразой, вынесенной в заголовок, я обычно руководствуюсь, когда встаёт вопрос — писать что-то на PHP самому или взять готовое?

Крайний раз этот вопрос встал по поводу шоппинг-карта для сайта автосервиса «Фортуна». Отсутствие каталога запчастей и возможности делать онлайн-заказы — зияющий пробел на их сайте, который будет устранён на будущей неделе. Естественно, выбранные позиции надо складывать в корзину, т. е. шоппинг-карт, по-русски говоря.

Готовых картов — море. С ними надо разбираться, приспосабливать к своему случаю, бороться с чужими глюками и ограничениями. И в итоге, даже если всё заработает — ты остаёшься там, где был, с нулевым приростом в знании.

К счастью, у меня был свой карт, написанный ранее по случаю. Симпатичный и простой. Удобно размазанный по четырём файлам, где его фрагменты надо было собрать, подправить, перенести куда надо...

Карт — предмет многократной продажи. Поэтому надо убить в него время, чтобы не убивать его потом снова и снова. Я убил день, с утра до вечера.

Получившийся шоппинг-карт выглядит так:

1) Находится в одном подключаемом файле.

2) Подробно документирован внутри: какие переменные ждёт, какие базы MySQL использует (включая SQL-директивы их создания), что устанавливает при выходе.

3) Настройки в начале, дальше черта, за которую ходить не надо.

4) Сам приспосабливается к таблицам каталога товаров. Фактически, всё, что от них действительно требуется — наличие поля price.

5) Сделан по принципу швейцарского ножа: будучи включён в веб-страницу, впрыскивает в неё стили и javascript-функции для работы карта; эти функции вызывают его самого через AJAX, в этом случае этот же файл работает как AJAX-интерфейс к базе данных; наконец, вызовом через POST его можно попросить отправить заказ по почте.

6) 286 (на момент) строк, из них 80 — комментарии.

7) Зависимости: prototype.js и моя бибилиотека wrapper'ов к PHP-функциям работы с MySQL.

пятница, октября 05, 2007

SQL.php: запросы одним вызовом

Когда-то, разрабатывая внутренний портал для одной компании, написал библиотеку полезных функций, среди которых были и несколько штук для быстрого получения данных из MySQL. Пользоваться ими оказалось так сподручно, что со временем я вынес эти функции в отдельный файл, добавил в его начало соединение с сервером MySQL и назвал всё это дело, не заморачиваясь, sql.php. С тех пор этот файл можно найти во всех веб-проектах, над которыми я работал. Наверное (даже наверняка), он ещё кому-то пригодится. Это не yet another MySQL wrapper, это даже меньше: несколько способов получить данные из базы одним вызовом.

query_into_array($query) — отдаёт результат запроса как массив ассоциативных массивов, каждый из которых — ряд результата в виде поле => значение.

query_into_assoc($query) — отдаёт один ряд результата в виде ассоциативного массива. То же, что и предыдущее, но для запросов, где ожидается единственный ряд.

query_into_enum($query) — Не то же самое, что предыдущее, и я сам иногда забываю эту разницу: возвращает левую колонку запроса, в котором может быть много рядов. Полезно, когда нужно получить значения какой-то поля.

query_into_keyvalue($query) — похоже на предыдущее, но возвращаются 2 левых колонки в виде ассоциативного массива, где индексы — значения первого поля, а значения — значения второго. Очень удобный способ выбрать проиндексированные данные, но чреват потерей части данных, если значения первого поля не уникальны.

query_into_var($query) — для запроса, возращающего единственное значение. Что там у нас в таком-то поле такого-то ряда?:

echo query_into_var($query);

Теперь, собссно, сама библиотечка. Очень простая, на живую нитку, но — работает, а что ещё от неё надо?

-------------------------------------------

$link = mysql_connect( "host", "user", "pass" );

/* Так можно настроить кодировки для MySQL 4.x
mysql_query("SET character_set_connection=cp1251");
mysql_query("SET character_set_results=cp1251");
mysql_query("SET character_set_server=koi8r");
mysql_query("SET character_set_client=cp1251"); */

/* А так — для 5.х
mysql_query("SET NAMES 'utf8'"); */

$db = mysql_select_db( "dbname" ) || die(mysql_error());

function query_into_array( $query ) {
$arr = array();
$n = 0;
$result = mysql_query( $query );
if ( ! mysql_affected_rows == 0 ) {
while ( $row = mysql_fetch_assoc( $result )) {
foreach ( $row as $key => $value ) {
$arr[$n][$key] = $value;
}
++$n;
}
mysql_free_result( $result );
}
return $arr;
}

function query_into_assoc( $query ) {
$result = mysql_query( $query );
if ($row = mysql_fetch_assoc( $result )) {
mysql_free_result( $result );
return $row;
}
}

function query_into_enum( $query ) {
$arr = array();
$result = mysql_query( $query );
if ( mysql_affected_rows() > 0 ) {
while ( $row = mysql_fetch_row( $result )) {
array_push( $arr, $row[0]);
}
mysql_free_result( $result );
}
return $arr;
}

function query_into_keyvalue($query) {
$arr=array();
$result = mysql_query( $query );
if (mysql_affected_rows()>0) {
while ($row= mysql_fetch_row($result)) {
$arr[$row[0]]=$row[1];
}
mysql_free_result( $result );
}
return $arr;
}

function query_into_var( $query ) {
return array_shift( query_into_enum( $query ));
}
?>





Поиск по этому блогу