Posts Tagged ‘php’

“Транзакционный” характер сессий в PHP

Monday, August 4th, 2008

...Сессия - не "информационное облако", это всего-лишь интерфейс к файлу, ....
сам по себе php не лочится, просто когда 2й процесс (скрипт) делает системный запрос на открытие файла - система его подвешивает и ждет освобождения ресурса. ...
(c)grigori

Эх, век живи – век учись. Еще какой-нибудь месяц назад я находился в блаженном неведении, $_SESSION мне представлялась именно тем “информационным облаком”, о котором писал grigori. Иллюзия разрушена.

Но на месте краха тут же возникли 3 новые истины:

1. session_init() подвешивает скрипт и ждет, когда остальные скрипты с открытыми сессиями и с такими же идентификаторами будут завершены или закроют сессии;

2. всвязи с этим, нужно открывать и закрывать сессии только когда это на самом деле необходимо. Не правильно поступать по принципу “открыть вначале и забыть”. Простейший пример: клиент ajaxом периодически дергает скрипты и пусть они написаны по этому принципу. В этом случае все эти скрипты не смогут работать паралельно, т.к. session_init() будет выступать в роли мьютекса. То есть, мало того, что производительность резко упадет (асинхронность отпадает сразу), есть вероятность “подвисания” всей этой системы, если какой-нибудь скрипт будет выполняться слишком долго.

3. session_set_save_handler – не выход, как это может показаться на самый первый взгляд. Действительно, можно сделать свой обработчик сессий так, чтобы session_init не “весила” все паралельно работающие скрипты. Но давайте вернемся к примеру из п2. Пусть есть один longplay скрипт, и за время его работы паралельно выполнились другие скрипты. В этом случае “callback $close” ? этого скрипта затрет все изменения $_SESSION, которые были сделаны другими скриптами пока он работал.

Таким образом, сессии в php носят “транзакционный” характер: session_init() = BEGIN TRANSACTION, session_write_close() = COMMIT, session_init() – мьютекс для всех скриптов с одним и тем же SESSID.

Excel (XLS) <-> CSV конвертация с помощью javascript-а и php

Saturday, July 26th, 2008

Наверняка любой php программист сталкивался с ситуацией, когда заказчик просит “экспорт товара из экзеля” или чего бы то ни было. И стон идет по всей земле русской (и нерусской)…

Первое, что приходит в голову – это каждый раз запускать Excel и сохранять файл в формате CSV, с которым php уже намного легче работать. Это – замечательное решение, когда число файлов меньше 10 и все они состоят только из одной страницы (поскольку экзель может экспортировать в CSV только страницы, те результат конвертации файла из 10 страниц будет 10 CSV файлов).

Вторая мысль: скачать какую-нибудь софтину, которая бы преобразовывала набор Excel файлов в CSV, включая все страницы. Но, погуглив чуток, сразу видно, что софтины эти все сплошь коммерческие. Можно, конечно, сломать.

Но есть и другой пусть: написать самому. Это очень легко реализуется, если использовать javascript и ActiveX компонент Excel.Application:

xls2csv.js

Этот скрипт необходимо поместить в папку с набором XLS файлов, создать папку output и tmp и набрать в коммандной строке:

cscript xls2csv.js

По завершении работы скрипта в output у нас появятся искомые CSV файлы, папку tmp можно почистить.

Для генерации Excel файлов на сервере я предпочитаю легкий класс ExcelWriter, написанный индусом Harish Chauhan-ом, тяжелому PEAR-овскому пакету Spreadsheet Excel Writer-у.

PHP: Определение браузера и операционной системы

Thursday, July 24th, 2008

http://techpatterns.com/downloads/php_browser_detection.php – Здесь находится отличный скрипт для определения браузера и операционной системы по строке $_SERVER['USER_AGENT']. Буквально выжимется ВСЕ возможное, влючая определение бот это или браузер:) Хотя понятно, что строка может быть легко подделана при желании.

А если добавить в конец файла browser_detection.php (который fully featured), то команда

require_once("browser_detection.php");

установит переменные $_SERVER['CLIENT_BROWSER'] и $_SERVER['CLIENT_OS'], в которых будут читабельные названия браузера и ОС соответственно. Код взят из примера на том же сайте

browser_detection.php

..........
..........
function browser_detection_initBD(){
    $os =  '';
    // change these two to match your include path/and file name you give the script
    $browser_info = browser_detection('full'); 

    $browser_info[] = browser_detection('moz_version'); 

    switch ($browser_info[5])
    {
                case 'win':
                    $os .= 'Windows ';
                    break;
                case 'nt':
                    $os .= 'Windows NT ';
                    break;
                case 'lin':
                    $os .= 'Linux ';
                    break;
                case 'mac':
                    $os .= 'Mac ';
                    break;
                case 'unix':
                    $os .= 'Unix Version: ';
                    break;
                default:
                    $os .= $browser_info[5];
    } 

    if ( $browser_info[5] == 'nt' )
    {
                if ($browser_info[6] == 5)
                {
                    $os .= '5.0 (Windows 2000)';
                }
                elseif ($browser_info[6] == 5.1)
                {
                    $os .= '5.1 (Windows XP)';
                }
                elseif ($browser_info[6] == 5.2)
                {
                    $os .= '5.2 (Windows XP x64 Edition or Windows Server 2003)';
                }
                elseif ($browser_info[6] == 6.0)
                {
                    $os .= '6.0 (Windows Vista)';
                }
                elseif ($browser_info[6] == 6.1)
                {
                    $os .= '6.1 (Windows 7)';
                }
    }
    elseif ( ( $browser_info[5] == 'mac' ) &&  ( $browser_info[6] >= 10 ) )
    {
                $os .=  'OS X';
    }
    elseif ( $browser_info[5] == 'lin' )
    {
                $os .= ( $browser_info[6] != '' ) ? 'Distro: ' . ucfirst ($browser_info[6] ) : 'Smart Move!!!';
    }
    elseif ( $browser_info[6] == '' )
    {
                $os .=  ' (version unknown)';
    }
    else
    {
                $os .=  strtoupper( $browser_info[6] );
    } 

    $browser = '';
    if ($browser_info[0] == 'moz' )
    {
                $a_temp = $browser_info[count( $browser_info ) - 1];// the moz array is last item
                $browser .= ($a_temp[0] != 'mozilla') ? 'Mozilla/ ' . ucfirst($a_temp[0]) . ' ' : ucfirst($a_temp[0]) . ' ';
                $browser .= $a_temp[1] . '; ';
                $browser .= 'ProductSub: ';
                $browser .= ( $a_temp[4] != '' ) ? $a_temp[4] . '; ' : 'Not Available; ';
                $browser .= ($a_temp[0] != 'galeon')?'RV version: ' . $a_temp[3] : '';
    }
    elseif  ( $browser_info[0] == 'ns' )
    {
                $browser .= 'Netscape ';
                $browser .= $browser_info[1] . '';
    }
    else
    {
                $browser .= ($browser_info[0] == 'ie') ? strtoupper($browser_info[7]) : ucwords($browser_info[7]);
                $browser .= ' ' . $browser_info[1];
    }
    $_SERVER['CLIENT_BROWSER'] = $browser;
    $_SERVER['CLIENT_OS'] = $os;
}
browser_detection_initBD();