Компонент AL_HGrid предназначен для представления информации справочного характера. Позволяет подключаться к базе данных (Access), делать SQL запросы. Изменять, добавлять записи в базе, а так же передавать выбранные данные в поля программы.
Прародителем сети интернет была сеть ARPANET. Первоначально её разработка финансировалась Управлением перспективного планирования (Advanced Research Projects Agency, или ARPA). Проект стартовал осенью 1968 года и уже в сентябре 1969 года в опытную эксплуатацию был запущен первый участок сети ARPANET.
Сеть ARPANET долгое время являлась тестовым полигоном для исследования сетей с коммутацией пакетов. Однако кроме исследовательских, ARPANET служила и чисто практическим целям. Ученые нескольких университетов, а также сотрудники некоторых военных и государственных исследовательских институтов регулярно её использовали для обмена файлами и сообщениями электронной почты, а так же для работы на удалённых компьютерах. В 1975 году управление сетью было выведено из под контроля ARPA и поручено управлению связи Министерства обороны США. Для военных данная сеть представляла большой интерес, так как позволяла сохранять её работоспособность даже при уничтожении её части, например, при ядерном ударе.
В 1983 году Министерство обороны разделило ARPANET на две связанные сети. При этом за сетью ARPANET были сохранены её исследовательские функции, а для военных целей была сформирована новая сеть, которую назвали MILNET. Физически сеть ARPANET состояла приблизительно из 50 миникомпьютеров типа С30 и С300, выпущенных фирмой BBN Corporation. Они назывались узлами коммутации пакетов и были разбросаны по территории материковой части США и Западной Европы. Сеть MILNET состояла приблизительно из 160 узлов, причём 34 из них были расположены в Европе, а 18 в Тихом Океане и в Азиатско-Тихоокеанском регионе. Сами узлы коммутации пакетов нельзя было использовать для решения вычислительных задач общего плана.
Понимая, что в ближайшем будущем очень важным моментом в научных исследованиях будет процесс обмена данными, Национальный научный фонд (NFS) в 1987 году основал отделение сетевых и коммуникацинных исследований и инфраструктуры. В его задачи входило обеспеченье современными сетевыми коммуникационными средствами учёных и инженеров США. И хотя отделение фонда NFS финансировало основные исследовательские программы в области сетевых коммуникаций, сферой его основных интересов было расширение Internet.
Сеть NSFNET строилась в несколько этапов и быстро преобретала популярность не только в научно-исследовательских кругах, но и в коммерческой среде. К 1991 году фонд NFS и другие государственные учреждения США поняли, что масштабы Internet вышли далеко за отведённые её на этапе разработки рамки университетской и научной сети. К Internet стало подключаться множество организаций, разбросанных по всему Земному шару. Трафик в магистральном канале NSFNET вырос почти до миллиарда пакетов в день, и его пропускной способности 1.5 Мбит/с на отдельных участках стало уже не хватать. Поэтому правительство США начало проводить политику приватизации и коммерческого использования Internet. Фонд NFS принял решение предать магистральную сеть на попечение закрытой акционерной компании и оплачивать доступ к ней для государственных научных и исследовательских организаций.
Семейство TCP/IP
Познакомившись с историей, давайте подробнее рассмотрим, что собой представляют протоколы TCP/IP. TCP/IP - это семейство сетевых протоколов, ориентированных на совместную работу. В состав семейства входит несколько компонентов:
IP (Internet Protocol - межсетевой протокол) - обеспечивает транспортировку пакетов данных с одного компьютера на другой;
ICMP (Internet Control Message Protocol - протокол управляющих сообщений в сети Internet) - отвечает за различные виды низкоуровневой поддержки протокола IP, включая сообщения об ошибках, вспомогательные маршрутизирующие запросы и подтверждения о получении сообщений;
ARP (Address Resolution Protocol - протокол преобразования адресов) - выполняет трансляцию IP-адресов в аппаратные MAC-адреса;
UDP (User Datagram Protocol - протокол передачи дейтаграмм пользователя) и TCP (Transmission Control Protocol - протокол управления передачей) - обеспечивают доставку данных конкретным приложениям на указанном компьютере. Протокол UDP реализует передачу отдельных сообщений без подтверждения доставки, тогда как TCP гарантирует надёжный полнодуплексный канал связи между процессами на двух разных компьютерах с возможностью управления потоком и контроля ошибок.
Протокол представляет собой набор правил, использующихся для при обмене данными между двумя компьютерами. В нём оговариваются формат блоков сообщений, описывается реакция компьютера на получение определённого типа сообщения и указываются способы обработки ошибок и других необычных ситуаций. И что самое важное, благодаря протоколам, мы можем описать процесс обмена данными между компьютерами, не привязываясь к какой-то определённой комьютерной платформе или сетевому оборудованию конкретного производителя.
Сокрытие низкоуровневых особенностей процесса передачи данных способствует повышению производительности труда разработчиков. Во-первых, поскольку программистам приходится иметь дело с протоколами, относящимися к достаточно высокому уровню абстракции, им не нужно держать в голове (и даже изучать!) технические подробности испольуемого аппаратного обеспечения. Во-вторых, поскольку программы разрабатываются на основе модели, относящейся к высокому уровню абстракции, который не зависит от конкретной архитектуры компьютера или типа сетевого оборудования, в них не нужно вносить никаких изменений при переходе на другой тип оборудования или изменений конфигурации сети.
Замечание Говорить о том, что ARP входит в состав семейства протоколов TCP/IP не совсем корректно. Однако это неотъемлемая часть стека протоколов в сетях Ethernet. Для того чтобы отправить данные по сети, IP-адрес хоста должен быть преобразован в физический адрес машины получателя (уникальный адрес сетевой платы). Протокол ARP как раз и предназначен для такой цели.
Самым фундаментальным протоколом Интернета является протокол IP (от англ. Internet Protocol), обеспечивающий передачу данных между двумя удаленными компьютерами. Протокол IP является достаточно простым, и обеспечивает адресацию в сети. В ранних сетях адреса в сети были уникальные целые цифры, сейчас сеть построена по иерархическому принципу.
Стек протоколов TCP/IP имеет четыре основных уровня, поэтому часто говорят, что TCP/IP — это четырехуровневый стек протоколов. Внизу стека расположен интерфейсный уровень, посредством которого происходит связь с аппаратурой. За ним следует уровень IP, поверх которого построены транспортные протоколы TCP и UDP. На вершине стека находится уровень приложений, таких как ftp, telnet и т. д. Как мы уже говорили, IP — это простой протокол, не требующий установления соединения. При отсылке пакета данных, IP, как и все протоколы без соединения, послав пакет, тут же "забывает" о нем. При приеме пакетов с верхних уровней стека, этот протокол обертывает их в IP-пакет и передает необходимому аппаратному обеспечению для отправки в сеть. Однако именно в такой простоте и заключается основное достоинство протокола IP. Дело в том, что поскольку IP является простым протоколом, он никак не связан со структурой физической среды, по которым передаются данные. Для протокола IP главное, что эта физическая среда в принципе способна к передаче пакетов. Поэтому IP работает как в локальных, так и в глобальных сетях, как в синхронном, так и в асинхронном режиме передачи данных, как в обычных линиях связи, так и беспроводных и т. д. А поскольку протокол IP является фундаментом четырехуровнего сте-ка протоколов, то все семейство протоколов TCP/IP также может функционировать в любой сети с любым режимом передачи пакетов.
На сетевом уровне в семействе протоколов TCP/IP предусмотрено два обширных класса служб, которые используются во всех приложениях.
Служба доставки пакетов, не требующая установки соединения.
Надёжная потоковая транспортная служба.
Различие между службами, требующими установления надёжного соединения и службами, не требующими этого, является одним из самых основных вопросов сетевого программирования. Первое, на что следует обратить внимание, это то, что когда мы говорим об установлении соединения, то имеется в виду не соединение между компьютерами посредством физического носителя, а о способе передачи данных по этому носителю. Основное различие состоит в том, что службы, в которых устанавливается надёжное соединение, сохраняют информацию о состоянии и таким образом отслеживают информацию о передаваемых пакетах. В службах же, не требующих надёжного соединения, пакеты передаются независимо друг от друга.
Данные передаются по сети в форме пакетов, имеющих максимальный размер, определяемый ограничениями канального уровня. Каждый пакет состоит из заголовка и полезного содержимого (сообщения). Заголовок включает сведения о том, откуда прибыл пакет и куда он направляется. Заголовок, кроме того, может содержать контрольную сумму, информацию, характерную для конкретного протокола, и другие инструкции, касающиеся обработки пакета. Полезное содержимое – это данные, подлежащие пересылке.
Имя базового блока передачи данных зависит от уровня протокола. На канальном уровне это кадр или фрейм, в протоколе IP – пакет, а в протоколе TCP – сегмент. Когда пакет передаётся вниз по стеку протоколов, готовясь к отправке, каждый протокол добавляет в него свой собственный заголовок. Законченный пакет одного протокола становится полезным содержимым пакета, генерируемого следующим протоколом.
Определение
Пакеты, которые посылаются протоколом, не требующим соединения, называются дейтаграммами.
Каждая дейтаграмма является уникальной в том смысле, что никак не зависит от других. Как правило, при работе с протоколами без установления соединения, диалог между клиентом и сервером предельно прост: клиент посылает одиночный запрос, а сервер на него отвечает. При этом каждый новый запрос — это новая транзакция, т. е. инициируемые клиентом запросы никак не связаны друг с другом с точки зрения протокола. Протоколы без установления соединения ненадежны в том смысле, что нет никаких гарантий, что отправленный пакет будет доставлен по месту назначения.
Протоколами, требующие установления логического соединения, сохраняют информацию о состоянии, что позволяет обеспечивать надежную доставку пересылаемых данных. Когда говорится о сохранении состояния, имеется ввиду то, что между отправителем и получателем происходит обмен информацией о ходе выполнения передачи данных. К примеру, отправитель, посылая данные, сохраняет информацию о том, какие данные он послал. После этого в течении определенного времени он ожидает информацию от получателя о доставке этих данных, и, если такая информация не поступает, данные пересылаются повторно.
Работа протокола с установлением соединения включает в себя три основные фазы:
установление соединения;
обмен данными;
разрыв соединения.
Передача всех данных при работе с таким протоколом, в отличие от протокола без установления соединения, происходит за одну транзакцию, т. е. в фазе обмена данными не происходит обмена адресами между отправителем и получателем, поскольку эта информация передается на этапе установки соединения. Возвращаясь к телефонной аналогии, можно сказать, что нам в этом случае нет необходимости для того, чтобы сказать собеседнику очередное слово, вновь набирать его номер и устанавливать соединение. Заметим, что приводимая аналогия имеет одну неточность. Дело в том, что при телефонном разговоре все же устанавливается физическое соединение. Когда же мы говорим о соединении с точки зрения протоколов, то это соединение, скорее, умозрительное. К примеру, если вдруг при телефонном разговоре, неожиданно сломается телефонный аппарат вашего собеседника, вы тут же узнаете об этом, поскольку разговор незамедлительно прервется. А вот если происходит обмен данными между двумя хостами и один из них вдруг аварийно остановится, то для его "хоста-собеседника" соединение по прежнему будет существовать, поскольку для него не произошло ничего такого, что сделало бы недействительной хранящуюся у него информацию о состоянии.
В этом смысле работу с протоколом, требующим установления логического соединения можно сравнить с телефонным разговором. Когда мы звоним по телефону, мы сначала набираем номер (установление соединения), затем разговариваем (обмен данными) и по окончании разговора вешаем трубки (разрыв соединения).
Протокол без установления соединения обычно сравниваю с почтовой открыткой. Каждая открытка представляет собой самостоятельную единицу (пакет информации или дейтаграмму), которая обрабатывается в почтовом отделении независимо от других открыток. При этом на почте не отслеживается состояние переписки между двумя респондентами и, как правило, нет никакой гарантии, что ваша открытка попадет к адресату. Если на открытке указан неправильный адрес, она никогда не дойдет до получателя, и не возвратиться обратно к отправителю. А если вы захотите отправить вашему собеседнику новую порцию информации, то это уже будет другая транзакция, поскольку нужно будет писать новую открытку, указывать на ней адрес и т. д.
Как видим, у протоколов без установления соединения существует много недостатков и может возникнуть вопрос о надобности таких протоколов. Однако, использование проколов без установления логического соединения все-таки оправдано. Как правило, при помощи таких протоколов организуется связь одного хоста со многими другими, в то время как при использовании протоколов с установлением соединения связь организуется между парой хостов (по одному соединению на каждую пару). Важный момент заключается в том, что протоколы без установления логического соединения являются фундаментом, на котором строятся более сложные протоколы. К примеру, протокол TCP построен на базе протокола IP.
Протоколы транспортного уровня
Протоколами транспортного уровня в четырехуровневом стеке протоколов являются протоколы TCP и UDP.
Давайте рассмотрим, каким образом функционирует протокол TCP. Дело в том, что поскольку TCP-пакеты, иначе называемые сегментами, посылаются при помощи протокола IP, у TCP нет никакой информации о состоянии этих пакетов. Поэтому для того, чтобы хранить информацию о состоянии, TCP к базовому протоколу IP добавляет три параметра.
Во-первых, добавляется сегмент контрольной суммы содержащихся в пакете данных, что позволяет убедиться в том, что в принципе все данные дошли до получателя и не повредились во время транспортировки.
Во-вторых, к каждому передаваемому байту приписывается порядковый номер, что необходимо для определения того, совпадает ли порядок прибытия данных с порядком их отправки. И даже в том случае, если данные пришли не в том порядке, в котором были отправлены, наличие порядковых номеров позволит получателю правильно составить из этих данных исходное сообщение.
В-третьих, базовый протокол IP дополняется также механизмами подтверждения получения данных и повторной отправки, на тот случай, если данные не были доставлены.
Если с первыми двумя параметрами все более-менее понятно, то механизм подтверждения/повторной отправки достаточно сложен и его мы рассмотрим подробнее в другой раз.
Конечно же вы попадали в такую ситуацию, когда приложение, разработанное вами ранее, могло быть снова использовано в рамках другого проекта. Вначале вы конечно же подумали, что это не создаст никаких проблем. Всего-то необходимо скопировать код из одного каталога в другой! Со временем вы осознали, что проекты могут различаться между собой различными параметрами, пусть даже самыми незначительными. Например, это может быть e-mail адрес на который отсылаются сообщения. В таком случае вам ничего не остается, как открыть множество файлов в редакторе и изменить их содержимое, вставляя нужный e-mail при помощи функции найти/заменить. Эта статья расскажет вам о том, как можно избавить себя от подобной работы, а так же порекомендует ряд дополнительных средств для создания и чтения конфигурационных файлов.
Повторное использование кода
Компьютер был изобретен для того, чтобы избавить человека от лишней работы. Развитие компьютерных технологий привело к тому, что человек стал стремиться все меньше времени проводить за компьютером. Допустим, вы программист. Не будь компьютера, вы бы остались без работы. Но в то же время вы стараетесь с помощью компьютера упростить свою ежедневную работы, с этой целью вы используете, например, функцию автозавершения кода в редакторе. Мы хотим подвести вас к той мысли, что код созданный вами, должен быть организован так, чтобы работы по его модификации были сведены к минимуму. Чаще всего это удается, когда вы создаете код, автоматизирующий рутинные операции, такие как создание и прорисовка формы, а так же отправка e-mail. Однако не стоит забывать, что функции для выполнения рутинных операций никогда не бывают на 100% идентичными в различных приложениях. Один формуляр не похож на другой, а сообщения электронной почты предназначены разным адресатам. Однако логика на уровне приложения остается прежней, функции различаются между собой только некоторыми параметрами. Таким образом, вы должны ясно представлять свою цель – разработать код, параметры которого можно было бы определять извне.
Модульная организация
Для решения этой задачи, планируя структуру приложения, вы должны позаботиться о модульности. То есть вам необходимо поместить часто используемые функции или классы в отдельный файл, который будет подключаться через require_once. В этом случае файлы приложения не будут наполнены избыточным кодом. Допустим, вы часто осуществляете запись в лог-файл. В таком случае было бы неплохо код, выполняющий эту операцию, заключить в рамки класса или функции. Будет еще лучше, если вы воспользуетесь уже готовым классом, взятым из какой-нибудь библиотеки исходных кодов, например PEAR.
Параметры процедурального кода
После того, как вы проанализировали код, выделили повторяющиеся фрагменты, распределили их по классам и функциям, необходимо подумать о выделении необходимых параметров, значения которых будут устанавливаться извне. Если речь идет о процедуральном коде, самым простым решением является использование глобальных переменных, которые необходимо определить в отдельном файле. Это позволит в дальнейшем без проблем изменять их значения.
Листинг 1 демонстрирует функцию, которая занимается отправкой e-mail. В ее теле содержится только одна php-функция - mail(). Таким образом, мы избавляемся от необходимости каждый раз указывать получателя при отправке сообщения. Следующая переменная, которую мы определяем, обозначает префикс, предшествующий теме сообщения. Конфигурационный файл, подключаемый через require_once, мог бы выглядеть следующим образом.
Listing 1
Есть способ лучше
Даже если рассмотренный выше способ и является действенным, однако это не самое лучшее решение. По мере того как код вашего приложения будет усложняться, вырастет и число опций, тогда могут возникнуть следующие проблемы:
Глобальные переменные, которые мы используем, могут породить конфликты в пространстве имен.
В том случае, если конфигурационные файлы редактируются не программистом, а дилетантом, в системе могут возникнуть синтаксические ошибки, например из-за незакрытых кавычек.
Для того, чтобы получить доступ к различным переменным, необходимо обращаться к массиву $_GLOBALS.
Вместо php-модулей существуют другие форматы, которые могут быть легко поняты и изменены дилетантами, а так же php-скриптами. Мы имеем в виду два формата: этого широко используемые операционной системой Windows ini-файлы, а так же формат XML.
PHP уже содержит функцию parse_ini_file(), которая без проблем читает ini-файлы. Такой файл имеет очень простую структуру. Каждой опции может быть присвоено только одно значение, а в качестве оператора присваивания используется знак равенства. Конфигурационный файл из предыдущего примера выглядел бы следующим образом в ini-формате.
После считывания ini-файла, имя которого передается в качестве параметра функции parse_ini_file(), мы получаем ассоциативный массив, имеющий вид:
В листинге 2 находится функция отправки почты, основанная на ini-файлах:
Listing 2
Если вы уже прочитали документацию по функции parse_ini_file(), вы кончено же заметили, что она может принимать и второй параметр. Он необходим, если вы хотите разделить ini-файл на несколько разделов или секций. Предположим, вам необходимо сохранить несколько настроек электронной почты. Тогда ini-файл будет выглядеть следующим образом:
"
Если вы при вызове parse_ini_file() передаете true в качестве второго параметра, в этом случае php будет искать в файле секции, а затем вернет многомерный массив, в котором каждой секции (errors и contact) будет соответствовать определенный набор значений:
Особые значения в ini-файлах
При использовании ini-файлов вы должны иметь в виду, что некоторые особые значения могут быть представлены строками. Допустим, вы определяете значение опции как true или yes (без кавычек), в таком случае они автоматически конвертируются в число 1, а false или no – в пустую строку. К сожалению, при этом не генерируется никакой ошибки. Поэтому не пытайтесь использовать no для сокращенного обозначения Норвегии.
Listing 3
Безопасность
Вы должны понимать то, что если конфигурационный файл используется для хранения важных данных, например паролей, необходимо позаботиться о том, чтобы содержимое такого файла не попало в web-браузер. Простейший выход из положения заключается в том, чтобы хранить конфигурационные файлы вне корневой директории сайта, например здесь: /etc/myApp/config
Если этого сделать нельзя, в таком случае можно изменить расширение файла. Для конфигурационного файла в формате модуля php необходимо всегда выбирать расширение .php. В этом случае сервер проанализирует php-файл, а пользователь увидит пустую страницу. С ini-файлами такое не пройдет, однако сервер Apache предоставляет возможность защитить данные. Просто поместите в каталог, где хранятся ini файл с именем .htaccess В него нужно поместить следующие строки:
Теперь сервер перестанет выдавать файлы с расширением ini, а опции приложения будут скрыты от пользователей.
Другие средства
Кончено же вы не являетесь единственным разработчиком, который сталкивается с проблемой обеспечения гибкости настроек веб-приложения. Поэтому некоторые программисты уже разработали библиотеки классов, которые переводят работу с конфигурационными файлами на абстрактный уровень, а так же упрощают запись и чтение различных форматов конфигурационных файлов.
PEAR::Config
Одним из классов, который может пригодится при чтении и записи конфигурационных файлов является PEAR::Config [3]. Как и все классы PEAR, PEAR::Config инсталлируется при помощи PEAR-Installer по команде
Этот класс является многоформатным, поскольку работает с конфигурационными файлами в форматах XMIL, ini, Apach-Style (гибрид XML и ini), а также php-массивами. Достоинством данного класса является то, что API для взаимодействия со всеми форматами одинаков. Т.е. логика работы с конфигурационными файлами в формате XML ничем не отличается от логики работы с ini-файлами. Вследствие этого необходимо, чтобы все форматы имели одинаковую структуру. Конфигурационные файлы, с которыми работает PEAR::Config, состоят, как и ini-файлы из секций.
Изменим снова наш пример. Сначала мы создаем объект Config, а затем вызываем его метод parseConfig(). Поскольку метод позволяет считывать различные форматы файлов, при вызове его необходимо передавать параметр, уточняющий формат. Для конфигурационных файлов в формате ini в качестве такого параметра используется строка iniFile. После считывания файла, мы не получаем опции в виде массива, вместо этого создается объект-контейнер, который дает доступ ко всем настройкам. Хотя во многих случаях бывает желательно получить опции в форме массива. Для этого используется метод toArray(). Листинг 4 демонстрирует считывание ini-файла:
Listing 4
С первого взгляда это может показаться несколько запутанным. Однако преимущество данного подхода заключается в том, что один и тот же метод используется для чтения всех форматов файлов, поддерживаемых PEAR::Config. Измененные опции могут быть также сохранены в любом формате:
Листинг 5 содержит код, где серия опций помещается в массив, который затем сохраняется в формате XML. Если вы хотите побольше узнать о PEAR::Config необходимую информацию вы сможете найти в документации по PEAR[5] или в DevShed-Tutorial [6].
Listing 5
patConfiguration
Альтернативным классом для работы с конфигурационными файлами является patConfiguration[7], однако он предназначен исключительно для работы с файлами в формате XML. После скачивания архива, его необходимо распаковать. Сам класс находится в директории include. patConfiguration предварительно определяет Tag-Set, который затем наполняется данными. К тому же этот класс предоставляет возможность указать тип опции: целое число, число с плавающей точкой, булевское значение. Типичный конфигурационный файл, созданный patConfiguration, имеет следующую структуру:
После создания объекта класса, может быть вызван метод parseConfigFile(). Доступ к опциям осуществляется через getConfigValue(). В качестве параметра этот метод может принимать путь к нужной опции. Вернемся к нашему примеру. Допустим, мы хотим получить e-mail адрес, на который высылается сообщение об ошибке. В этом случае используется путь errors.email. Если путь не указан, тогда все параметры передаются в массив. Листинг 6 демонстрирует код, который можно использовать для считывания файлов.
patConfiguration 2.0.0
В данный момент многоформатная версия patConfiguration находится в стадии разработки. Возможно, при публикации статьи эта версия уже станет доступной. Впрочем, самую новую версию для разработчиков вы можете скачать с сайта snaps.php-tools.net/downloaden.
В этом примере вы уже заметили, что внутри тега указывается тип значения. Названия типов идентичны тем, что используются в php-функции settype(). Если тип не указан, тогда значение интерпретируется как строка. Для часто используемых опций можно определить отдельный тег.
Наряду с функцией getConfigValue, существует функция setConfigValue(), с помощью которой можно изменить значение опции. Затем конфигурационный файл может быть заново записан с помощью writeConfigFile() (см листинг 7).
patConfiguration предлагает также серию дополнительных возможностей. Например, наряду с тегами, существует возможность определять атрибуты и пространства имен (Namespace), а к тегу можно привязать внешний файл, таким образом, опции будут распределены по нескольким файлам. Кроме этого patConfiguration включает систему кэширования, благодаря которой пропадает необходимость в многократном считывании конфигурационного файла.
Дополнительную информацию вы сможете найти на PHP Application Tools-Homepage и в patConfiguration-Tutorial на DevShed [8].
Listing 7
Заключение
Забота о гибкости настроек приложения может сберечь много времени, особенно если его компоненты предполагается использовать в других проектах. Вы потратите еще меньше времени, если доверите работу с конфигурационными файлами одному из готовых классов. Выбор между PEAR::Config и patConfiguration зависит от задачи. Преимуществом PEAR::Config является поддержка различных форматов конфигурационных файлов, в то время как patConfiguration прекрасно работает с XML, так же предоставляет ряд дополнительных возможностей. Однако с появлением версии 2.0.0 этот пакет будет иметь одинаковый API для считывания ini и wddx файлов. PHP-массив поддерживаются уже в текущей версии.