Невозможно публиковать контент, начинающийся с «@», с помощью Guzzle

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

$input = array('status' => '@abhishekm2040 Hi with screenname again.', 
           'in_reply_to_status_id' => '2345454545'); 

Затем я получаю сообщение об ошибке для содержимого состояния

 "message": "Unable to open abhishekm2040 Hi with screenname again. for reading",

из-за следующего кода:

__src/третьих сторон/Guzzle/Http/Message/RequestFactory.php

if (is_array($body) || $body instanceof Collection) {
                // Normalize PHP style cURL uploads with a leading '@' symbol
                foreach ($body as $key => $value) {
                    if (is_string($value) && substr($value, 0, 1) == '@') {
                        $request->addPostFile($key, $value);
                        unset($body[$key]);
                    }
                }
                // Add the fields if they are still present and not all files
                $request->addPostFields($body);
            }

пожалуйста, дайте мне знать, как я могу решить эту проблему.

https://github.com/guzzle/guzzle3/issues/57


person Abhishek Mittal    schedule 13.05.2015    source источник
comment
Кажется, что эта библиотека обрабатывает сообщение тела с @ в начале как участие в загрузке файла ($addPostFile). Почему бы не использовать специальную библиотеку twitter API?   -  person Ofir Baruch    schedule 13.05.2015
comment
Я взял Твиттер просто в качестве примера.   -  person Abhishek Mittal    schedule 14.05.2015


Ответы (2)


Начнем с понимания почему.

Guzzle использует cURL, поэтому я просмотрел руководство по php cURL и, согласно ему, вот определение CURLOPT_POSTFIELDS (которая "отвечает" за данные):

Полные данные для публикации в операции HTTP "POST". Чтобы опубликовать файл, добавьте к имени файла символ @ и укажите полный путь. Тип файла можно указать явно, указав после имени файла тип в формате ';type=mimetype'. Этот параметр может быть передан либо в виде строки с URL-адресом, например «para1=val1¶2=val2&...», либо в виде массива с именем поля в качестве ключа и данными поля в качестве значения. Если значение является массивом, для заголовка Content-Type будет задано значение multipart/form-data. Начиная с PHP 5.2.0, значение должно быть массивом, если файлы передаются в эту опцию с префиксом @. Начиная с PHP 5.5.0, префикс @ устарел, и файлы можно отправлять с помощью CURLFile. Префикс @ можно отключить для безопасной передачи значений, начинающихся с @, установив для параметра CURLOPT_SAFE_UPLOAD значение TRUE.

Таким образом, поведение, о котором вы упомянули, является рациональным и логичным. Обратите внимание на последние 2 строки в объяснении выше:

Начиная с PHP 5.5.0 префикс @ устарел, и файлы можно отправлять с помощью CURLFile. Префикс @ можно отключить для безопасной передачи > значений, начинающихся с @, установив для параметра CURLOPT_SAFE_UPLOAD значение TRUE.

Решением было бы установить для параметра CURLOP_SAFE_UPLOAD значение TRUE, но, поскольку вы используете фреймворк, это потребует некоторой работы. Что-то типа:

//Ваш новый входной массив

$input = array('status' => '@abhishekm2040 Hi with screenname again.', 
           'in_reply_to_status_id' => '2345454545',
           'ignore_a' => true);

И в коде фреймворка:

            if(isset($body['ignore_a']) && $body['ignore_a']){
               $ignore_a = true;
               //Here you should set the curlop_safe_upload option to true.
               //Since i'm not familiar with that framework I don't know
               //how to do it.
               //Update: It seems that the framework doesn't has a `setCurlOpt` function so you'll just have to write one.
            } else {
               $ignore_a = false;
            }

            foreach ($body as $key => $value) {
                if (!$ignore_a && is_string($value) && substr($value, 0, 1) == '@') {
                    $request->addPostFile($key, $value);
                    unset($body[$key]);
                }
            }

(Обратите внимание, что я не тестировал этот код, и он был написан только для того, чтобы показать общую идею)

Если учесть первую часть последних двух строк: префикс @ устарел, как и в PHP 5.5.0. Это означает, что, возможно, в более новой версии этого фреймворка у вас этого не произойдет.

Я добавил ссылку на этот ответ в вашу ветку GitHub. Обратите внимание, что поскольку у этого фреймворка уже есть более новая версия, разработчики могут не работать над ним и просто предложат вам получить более новую версию.

person Ofir Baruch    schedule 14.05.2015
comment
Помогло ли оно вам найти способ решить вашу проблему? - person Ofir Baruch; 14.05.2015
comment
Спасибо за решение, но модификация в сторонней библиотеке не очень хорошая идея. Попытка обновить стороннюю библиотеку Guzzle... - person Abhishek Mittal; 15.05.2015

Моя проблема решена, когда я обновил последнюю библиотеку Guzzle.

Спасибо Офиру Баруху за направление

person Abhishek Mittal    schedule 28.05.2015