Так-же рекомендую обратится к первоисточнику.
Вводные данные:
-
Обвёртка (wrapper) позволяет расширить стандартные файловые функции (fopen(), readdir()…) для работы с разнообразными протоколами и
типами данных. Использовать их просто: вызов fopen(‘http://www.google.com’); использует обвёртку "http"
Посмотреть список системных обвёрток можно здесь: http://php.net/manual/en/wrappers.php. -
Atom — это основанный на XML формат, предназначенный для новостных лент, анонсов статей и так-далее.
От RSS отличается, но служит для тех-же целей. Как-правило, даже если используют Atom всеравно пишут RSS.
И собственно Atom-файл:<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title> Feed Title </title> <link href=" http://yourwebsite.com/"/> <updated>2003-12-13T18:30:02Z</updated> <author> <name>Your Name</name> </author> <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id> <entry> <title>Article Title</title> <link href=" http://yourwebsite.com/articlelink.html "/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2003-12-13T18:30:02Z</updated> <summary>Some text.</summary> </entry> <entry> <title>Sports</title> <link href=" http://yourwebsite.com/sportslink.html "/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344e45ab90</id> <updated>2003-12-14T13:30:55Z</updated> <summary>Some text.</summary> </entry> </feed>
Описание:
bool stream_wrapper_register(string $protocol, string $classname)
— регистрирует пользовательскую обвёртку. Возвращает true в случае успеха и false в противном случае.
Если обвёртка уже существует, то функция ее не переопределяет и возвращает false. В этом случае нужно делать так:
//Удаляем существующую обвёртку
stream_wrapper_unregister('http');
...
//Регистрируем свою
stream_wrapper_register('http', 'CustomHTTP');
//Здесь используем свою обвёртку
...
//Востанавливаем предыдущую обвёртку
stream_ wrapper_ restore('http');
bool stream_wrapper_unregister(string $protocol)
bool stream_wrapper_restore(string $protocol)
Первая функция удаляет существующую обвёртку, вторая — востанавливает удаленную раннее обвёртку.
Обе функции возвращают true в случае успеха и false в противном случае.
В класе обвёртке нужно определить методы для файловых функций.
Они должны быть определены именно так, как указано ниже. Шаг влево, шаг вправо карается багами!
bool stream_open(string $path, string $mode, int $options, string $opened_path)
Этот метод вызывается сразу после открытия потока функцией fopen().
$path — имя файла, переданоё в fopen().
$mode — режим открытия файла из fopen().
$options — содержит дополнительные флаги, переданные системой.
Опции соеденены через OR.
STREAM_USE_PATH — если $path содержит относительный путь,
указывает на поиск ресурса с использованием include_path
STREAM_REPORT_ERRORS — если флаг установлен, метод несет ответственность за установку ошибок
через trigger_error(), в противном случае метод не должен выставлять никаких ошибок.
$opened_path — если ресурс открыт успешно и в $options установлен
флаг STREAM_USE_PATH, метод должен вернуть сюда полный путь к открытому ресурсу.
void stream_close(void)
Метод вызывается при закрытии потока, используя fclose().
string stream_read(int $count)
Метод вызывается при использывании fread() и fgets().
Метод должен вернуть не более $count байт, начиная с текущей позиции файлового указателя.
Если байти закончились — нужно вернуть FALSE. Так-же нужно сместить файловый указатель на количество успешно прочитаных байт.
Далее кратко.
bool stream_eof(void) — для feof();
int stream_tell(void) — для ftell();
bool stream_seek(int $offset, int $whence) — для fseek();
bool stream_flush(void) — для fflush();
array stream_stat(void) — для fstat();
bool unlink(string $path) — для unlink() PHP >= 5.0.0;
bool rename(string $path_from, string $path_to) — для rename() PHP >= 5.0.0;
bool mkdir(string $path, int $mode, int $options) — для mkdir() PHP >= 5.0.0;
bool rmdir(string $path, int $options) — для rmdir() PHP >= 5.0.0;
array url_stat(string $path, int $flags) — для rmdir();
bool dir_opendir(string $path, int $options) — для opendir();
Все функции ниже работают посе dir_opendir().
string dir_readdir(void) — для readdir() ;
bool dir_rewinddir(void) — для rewinddir();
bool dir_closedir(void) — для closedir();
Кодинг:
Класс написан на скорую руку и служит только для иллюстрации принципа написания класса обвёртки. Имена тегов заране известны, документ валиден, проверки отсутствуют, коментарии на русском.
<?php
function dump($aData){
echo '<pre>';
print_r($aData);
echo '</pre>';
}
class AtomStreem{
private $handler;
private $raw_data = array();
private $data = array();
private function _GetEntryes(){
$i = 0;// Счётчик елементов
$entry = false;
foreach ($this->raw_data as $idx => $row) {
if (strpos($row, '<entry>') !== false)
$entry = true;
// Начало элемента
if (strpos($row, '</entry>') !== false){
$entry = false;
$i++;
}
// Конец элемента
if ((strpos($row, '<title>') !== false) && $entry){
// Если в строке есть "<title>" и строка в элементе
$row = str_replace('<title>', '', $row);
$row = str_replace('</title>', '', $row);
$row = trim($row);
// Обрезаем всё лишнее
$this->data[$i]['title'] = $row;
unset($this->raw_data[$idx]);
// Удаляем обработанную строку
}
if ((strpos($row, '<link ') !== false) && $entry){
$row = str_replace('<link href="', '', $row);
$row = str_replace('"/>', '', $row);
$row = trim($row);
$this->data[$i]['link'] = $row;
unset($this->raw_data[$idx]);
}
if ((strpos($row, '<id>') !== false) && $entry){
$row = str_replace('<id>', '', $row);
$row = str_replace('</id>', '', $row);
$row = trim($row);
$this->data[$i]['id'] = $row;
unset($this->raw_data[$idx]);
}
if ((strpos($row, '<updated>') !== false) && $entry){
$row = str_replace('<updated>', '', $row);
$row = str_replace('</updated>', '', $row);
$row = trim($row);
$this->data[$i]['updated'] = $row;
unset($this->raw_data[$idx]);
}
if ((strpos($row, '<summary>') !== false) && $entry){
$row = str_replace('<summary>', '', $row);
$row = str_replace('</summary>', '', $row);
$row = trim($row);
$this->data[$i]['summary'] = $row;
unset($this->raw_data[$idx]);
}
}
}
private function _GetInfo(){
// Обрабатываем остатки данных
foreach ($this->raw_data as $row) {
if (strpos($row, '<title>') !== false){
$row = str_replace('<title>', '', $row);
$row = str_replace('</title>', '', $row);
$row = trim($row);
$this->data['title'] = $row;
}
if (strpos($row, '<link href="') !== false){
$row = str_replace('<link href="', '', $row);
$row = str_replace('"/>', '', $row);
$row = trim($row);
$this->data['link'] = $row;
}
if (strpos($row, '<updated>') !== false){
$row = str_replace('<updated>', '', $row);
$row = str_replace('</updated>', '', $row);
$row = trim($row);
$this->data['updated'] = $row;
}
if (strpos($row, '<name>') !== false){
$row = str_replace('<name>', '', $row);
$row = str_replace('</name>', '', $row);
$row = trim($row);
$this->data['name'] = $row;
}
if (strpos($row, '<id>') !== false){
$row = str_replace('<id>', '', $row);
$row = str_replace('</id>', '', $row);
$row = trim($row);
$this->data['id'] = $row;
}
}
}
private function _Parce(){
$this->_GetEntryes();
$this->_GetInfo();
}
/**
* Функция для fopen()
*
* @param string $path
* @param string $mode
* @param int $options
* @param string $opened_path
* @return bool
*/
public function stream_open($path, $mode, $options, $opened_path){
$_path = parse_url($path);
$_path = $_path['host'] . $_path['path'];
// Предыдущее 2 строчки извлекают из строки $path сщбственно путь,
// отбрасывая схему ("atom://" в нашем случае).
$this->handler = fopen($_path, $mode);
return true;
}
/**
* Функция для fgets()
*
* @param int $count
* @return string
*/
public function stream_read($count){
while (($row = fgets($this->handler)) !== false){
// ($row = fgets($this->handler)) !== false - присваивание в условии - плохой тон.
// Дедаем из присваивания условие
$this->raw_data[] = $row;
}
// Помещаем содержимое файла в свойство $this->data.
$this->_Parce();
// Парсим содержимое файла
return serialize($this->data);
// serialize() - потому-что функция должна возвращать string
}
/**
* Функция для fclose()
*/
public function stream_close(){
// Здесь освобождаем ресурсы
fclose($this->handler);
unset($this->handler);
unset($this->raw_data);
unset($this->data);
}
/**
* Функция для feof()
* У функции fgets(), в отличии от fread() параметр $length необязателен.
* На самом деле fgets() - это цикл, вызывающий fread() с длинной 1байт и feof().
*
* @return bool
*/
public function stream_eof(){
if (count($this->data))
return true;
return false;
}
}
stream_wrapper_register('atom', 'AtomStreem');
// Регистрируем обвёртку
$fp = fopen('atom://./atom.xml', 'rb');
dump(unserialize(fgets($fp)));
// unserialize() - смотри метод stream_read()
fclose($fp);
?>
Результат работы:
Array
(
[0] => Array
(
[title] => Article Title
[link] => http://yourwebsite.com/articlelink.html
[id] => urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a
[updated] => 2003-12-13T18:30:02Z
[summary] => Some text.
)
[1] => Array
(
[title] => Sports
[link] => http://yourwebsite.com/sportslink.html
[id] => urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344e45ab90
[updated] => 2003-12-14T13:30:55Z
[summary] => Some text.
)
[title] => Feed Title
[link] => http://yourwebsite.com/
[updated] => 2003-12-13T18:30:02Z
[name] => Your Name
[id] => urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6
)
Вот, собственно, и всё.
http://php.net/manual/ru/wrappers.php — ссылка не работает.
Спасибо, поправил. Русскую ветку мануала убрали.
Так почему так и не поставили капчу? Вроде на WP легко
потому-что поставил wp-spamfree.
Раздражает меня капча. Думаю, многих тоже.
Без каптчи вам так они всё заспамят…
Скорее всего — нет.
Почему? — wp-spamfree. Правда, поставить — руки никак не доходят. Почитать об этом плагине можно здесь.