Pull to refresh

Comments 71

Статья хороша, правда возникает такое ощущение, что код выхвачен как-то случайно. Раз уж выкладывать пример, дак такой, где и модули есть оставшиеся, и тег ?> закрыт. А в целом все позитивно :)
Да, и еще неплохо запрос формировать через http_build_query, но это уже мелочи. Спасибо за статью
UFO just landed and posted this here
отсутствие тега ?> добавляет некую загадку,… чувство незавершенности статьи, значит следует ждать продолжения… романтика млин=)
Если закрывать ?> потом будешь искать кто в хедер данные шлет до тебя )) очень часты запар. Так что лучше не закрывать…
Даже разработчики Zend Framework не рекомендуют закрывать тег ?>
И в стандартах кодирования, принятых в CodeIgniter, черным по белому таки написано: не ставить закрывающий "?>".
Интересно, сколько еще народу скажет, что "?>" ставить не рекомендуется и подкрепит свои слова разными примерами из жизни? :-D
Неоднократно сталкивался с подобными задачами, однако, помимо банального POST'а часто еще нужно отправить и Cookie, или вообще файл. А вообще, имхо, CURL, а уж тем более сокеты гораздо лучше в плане того, что позволяют разобраться лучше в принципах работы HTTP-протокола, ну и естественно имеют значительно больше возможностей.
Это просто еще один удобный инструмент.
Сомнительное удобство…
Cookie отправить элементарно — просто указывается ещё один заголовок. С файлом проблемы, я хорошего способа не знаю, кроме как сделать всё руками.
Приемлимый способ заключается в использовании настоящего курла:
curl -c cookies.jar -b cookies.jar -F subno=@file.txt
Я рассуждаю в рамках статьи.
Простите,
exec('curl -c cookies.jar -b cookies.jar -F subno=@file.txt')
Вот теперь в рамках статьи :)
:))
В PHP всё-таки есть модуль CURL, один из самых старых.
Совершенно верно.

Плюс еще модифицировать user-agent или referer, поэтому имхо я считаю, правильным то, что универсальное.
«Своим» file_get_contents вы возьмете контент только на 50% сайтов, что недопустимо мало.
Через сокеты 99%, что закончится успехом.

«Это» нельзя даже предлагать как одно из решений.
Работа через file_get_contents с удаленными данными — это Зло.
Да и вообще, почаще заглядывайте на php.net, чтобы не писать такие топики ;)

Имхо я пользуюсь сокетами, это более универсальное решение.
UFO just landed and posted this here
Ну так по такой логике и контексты потока использовать — слишком низкий уровень. Нет? =)
решение работает только на серверах с fopen = true, и с PHP >= 5. в совокупности таких около 40%
поэтому для универсальных решений используют curl.
Есть только одно оправдание разработчику не использующему curl — массовый дешевый коммерческий продукт, который реально инсталлируют тысячи на всевозможных кривущих хостингах. Вы именно такой пишите?
имхо всё совсем наоборот. универсальное массовое решение должно как минимум год-два поддерживать версию PHP 4.x. увы, дешевые hosting провайдеры очень медленно переходят на пятёрку.
это вы о чем? дешевые хостинг провайдеры берут не качеством, а количеством, поэтому им наиболее важно написать кучу плюсов(а это и php5), но работать не качественно(саппорт).
к сожалению даже на 1&1 четверка стоит
да ну? :)
faq.1and1.com/scripting_languages_supported/php/9.html

мне вообще не попадались хостеры среди более-менее популярных, не поддерживающие PHP5 тем или иным способом
Контексты в пятёрке появились, если не путаю.
>>Чтобы получить содержимое веб-страницы все с удовольствием используют file_get_contents()
наглая ложь :) cURL для того и сделан, чтобы было легче жить, все что нужно уже сделано, cookies например.

ps: я не против концепции ооп, но когда вы даете пример примитивной операции — не нужно его заворачивать в свои лишние методы — это напрягает, приходится бегать глазами и вытаскивать строчки. Донесите до читателя смысл 3-4мя строчками вместо класса и пары инклюдов, а он уже сам решит где и как у себя это применить(ведь маловероятно, что он начнет применять ваш класс у себя).
Тяжело читать статьи, когда код большой и совершенно не адаптирован для быстрого восприятия.
RTFM данный вами в тысячу раз понятнее — угадайте почему :)
Согласен. Просто добавил пару тестов — уже разучился доверять коду без тестирования.
Ну как на хабре без понта? ))
Как мне показалось, ничуть не проще курла. Тем более когда послдний знаешь :)
быстрее имхо курлом это сделать, а может мне просто курлом привычнее… от этого и быстрее
как-то вы странно тестируете код.
один из столпов модульного тестирование — изоляция. т.е. тесты не должны зависеть ни от чего снаружи. все действия по созданию рабочей среды должны производиться в фикстурах, а по воспроизведению тестовых прецедентов — в тестовых методах.
как-то так
В соответствии с задачей: быстро, дешево и в одном файле
«правильно» (см. по общепринятым стандартам) написанный тест был бы нисколько не больше по числу строк и занял бы ни капли не больше времени.
как показала практика file_get_contents жутко тормознутый в сравнении с курлом
Дабы не создавать отдельную тему… Есть замечание насчет file_get_contents…

По мануалу «It will use memory mapping techniques if supported by your OS to enhance performance. »

НО:

php -r '$data = file_get_contents("/media/STORAGE/Downloads/ubuntu-8.10-desktop-i386.iso");'
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 732774400 bytes) in Command line code on line 1

То есть он пытается весь файл загнать в оперативку и ни о каком memory mapping речи и нет…
Система Ubuntu 8.10 i686

Может mmap где-то отдельно включается или я не понимаю его сути? Может кто разъяснить?
Все логично — вы же в переменную присваиваете, а вы, допустим, ехайте его?
чего с ним делать?

Нет, на первый взгляд все работает как обещано.
Файл хоть и помещается в общую виртуальную кучу php, на самом деле содержимое не обязательно в нее считывается. Это можно узнать запустив через strace. Вот я запустил:

open("/usr/lib/vmware/isoimages/linux.iso", O_RDONLY|O_LARGEFILE) = 3
fstat64(3, {st_mode=S_IFREG|0444, st_size=34963456, ...}) = 0
_llseek(3, 0, [0], SEEK_CUR) = 0
fstat64(3, {st_mode=S_IFREG|0444, st_size=34963456, ...}) = 0
mmap2(NULL, 34963456, PROT_READ, MAP_SHARED, 3, 0) = 0xb5197000
mmap2(NULL, 35131392, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb3016000
munmap(0xb5197000, 34963456) = 0
close(3) = 0
Это тоже было моей первой мыслью, но если пробовать без "$data =" — все совершенно тоже самое.
Конечно, file_get_contents запихивает все содержимое файла в оперативку. Для этого оно и было придумало — получить одной строкой все содержимое файла или url. Не нравится — самое первое, что приходит в голову: fopen, fread, fwrite, fclose. Они для подобных целей и были сделаны.
Да не запихивает. Смотрите трассировку системных вызовов чуть выше.

Поделитесь лучше идеями как хранить в разделяемой памяти не только строки, но и произвольные структуры языка.
Это даст возможность появиться очень интересным оптимизациям в вебе до сих пор не имеющим аналогов.
Вы не указали, что это доступно только начиная с 5.1.х

И еще, народ используется file_get_contents() из-за минимализма кода (в четверке использовали $var = implode("", file("/path/to/file")) и прочие конструкции), а если для отправки постом нужна такая оберкта, то, ИМХО, гораздо проще курл использовать… (да и возможностей в нем всяко больше)
А я пользуюсь PEAR:HTTP_Request и очень доволен
Там все очень просто, разобратся можно очень быстро.
Вот пример:

<?php
require 'HTTP/Request.php'
$http = new HTTP_Request('http://habrahabr.ru');
$http->setMethod(HTTP_REQUEST_METHOD_POST);
$http->addPostData('test', 1);

$http->sendRequest();
$http->getResponseBody(); //тело ответа
$http->getResponseCode()
Хабр заглючил — отправилось раньше
<?php
require 'HTTP/Request.php'
$http = new HTTP_Request('http://habrahabr.ru');
$http->setMethod(HTTP_REQUEST_METHOD_POST);
$http->addPostData('test', 1);

$http->sendRequest();
$http->getResponseBody(); //тело ответа
$http->getResponseCode(); //код ответа
$http->getResponseHeader(); //хидеры
$http->getResponseCookies(); //куки
Зачем столько кода, показывать какой ты крутой умеешь писать под рнр5 паблики приваты… когда основная идея лежит в 3м параметре функции… про него и надо было просто написать.

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

Сделал интересное открытие для себя этим контекстом. Но практичнее CURL в модуле, дабы подсунуть Referer, Cookies, etc.
реферер и куки — это header's
куки подсовываются указателем на файл — и парсить не надо, и соблюдать RFC — куда практичнее, чем велосипеды.
PHP_EOL в конце заголовка (Content-Type) — дурь какая-то.
Просто не все читают спецификации.
Просто можно было вместо
>>> 'Content-Type: application/x-www-form-urlencoded'. PHP_EOL
написать
>>> «Content-Type: application/x-www-form-urlencoded\r\n»
Когда удалил второй заголовок, забыл убрать EOL.
Сейчас открыл RFC,- и правда — CRLF. Как снес windows уже отвык от \r\n.
Иногда возникает такое чувство, что разработчики PHP придерживаются некой догмы, согласно которой одно и тоже может быть реализовано как минимум 3-мя различными способами. Это конечно здорово, только не всегда понятно зачем это нужно.

Я думаю так, вот был раньше file_get_contents, внутри которого при обращении к url этот саный контекст создавался. И вот в новой версии разработчики решили — а зачем это мы будем генерить свой контекст, если можно сделать так, что б использовался внешний. Сказано сделано — ввели еще один не обязательный параметр. Т.е. наличие данной особенности не потому что она нужна, а потому что она легко реалтизуется. И может кому-нибудь пригодится. И все.

CURL-то конечно удобнее.
CURL в одну строчку контент не получишь, бывают моменты, когда нужно что то сделать быстро.
А вот это:
$context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded' . PHP_EOL,
'content' => QUERY,
),
));

// Отправить запрос на себя, чтобы запустить тесты
// и показать результат выполнения тестов
echo file_get_contents(
$file = "http://{$_SERVER['HTTP_HOST']}{$_SERVER['PHP_SELF']}?runTests",
$use_include_path = false,
$context);

Одна строчка?
Прям 1000 и 1 способ собрать велосипед… :)

Мне всегда хватало libcurl для всевозможных HTTP запросов, к тому же он знает, что такое таймауты. Единственный только его минус — не умеет хранить куки в памяти, как например тот же libwww в Perl. Или может в данном направлении прогресс уже произошёл?
> к тому же он знает, что такое таймауты
docs.php.net/manual/ru/context.http.php — timeout там присутствует.

> не умеет хранить куки в памяти
это как? чтобы их каждый раз не указывать при запросе? не понял просто.
В оригинале у libcurl поболее всяких таймаутов поддерживает, но не уверен что их все в PHP включили.
curl.haxx.se/libcurl/c/curl_easy_setopt.html

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

я малость поумнел с тех пор и догнал, что куки хранятся в памяти, если в качестве CURLOPT_COOKIEJAR указать пустую строку :)
Как говорит один мой умный знакомый, можно и отвертку вместо молотка использовать, главное — бить сильно и метко.
UFO just landed and posted this here
блин, вот ведь лень до чего доводит! читать надо маны, читать.

спасибо автор.
Ёлки-палки! Два месяца использую PHP в подобном роде. Всё время рисовал свои грабли через сокеты. Вчера увидел про CURL, решил что буду гуглить его, и вот — зарегестрировался на хабре и прозрел, каким был идиотом.

Мануалы читать надо! :)

Автору гигантский респект за наставление на пусть истинный. Только что -1.2кб кода и +80 к читаемости. :)
С версии 5.3.0 контекст принимает так же copy();
Sign up to leave a comment.

Articles