Статьи

Комментирование, голосование и загрузка фотографий с помощью API 500px

В первой части этой серии мы использовали API для получения последних фотографий размером 500px и их фильтрации, а также создали профиль пользователя со списком связанных фотографий. В этой части мы дадим пользователю возможность голосовать, добавлять в избранное и комментировать фотографии, и, наконец, мы дадим пользователям возможность загружать свои собственные фотографии. Давайте начнем.

Logo

авторизация

При попытке доступа к конечной точке API нам необходимо проверить уровень аутентификации, необходимый для доступа к ресурсу. Для API может потребоваться consumer_key или OAuth .

В первой части мы зарегистрировали новое приложение на 500px и получили наши consumer_key и consumer_secret . Мы используем приложение Grant , чтобы получить действительный token и token_secret для тестирования.

Аутентификация

После указания ваших token_secret и consumer_secret вы получите token и token_secret . Это даст вам право публиковать и получать пользовательский контент.

 // bootstrap/start.php App::singleton('pxoauth', function(){ $host = 'https://api.500px.com/v1/'; $consumer_key = 'YOUR CONSUMER KEY'; $consumer_secret = 'YOUR CONSUMER SECRET'; $token = 'GRANT TOKEN'; $token_secret = 'GRANT TOKEN SECRET'; $oauth = new PxOAuth($host, $consumer_key, $consumer_secret, $token, $token_secret); return $oauth; }); 

Класс PxOAuth оборачивает наше общение с помощью API 500px.

 // app/src/PxOAuth.php class PxOAuth{ public $host; public $client; private $consumer_key; private $consumer_secret; private $token; private $token_secret; public function __construct($host, $consumer_key, $consumer_secret, $token, $token_secret){ $this->host = $host; $this->consumer_key = $consumer_key; $this->consumer_secret = $consumer_secret; $this->token = $token; $this->token_secret = $token_secret; $params = [ 'consumer_key' => $this->consumer_key, 'consumer_secret' => $this->consumer_secret, 'token' => $this->token, 'token_secret' => $this->token_secret ]; $oauth = new Oauth1($params); $this->client = new Client([ 'base_url' => $this->host, 'defaults' => ['auth' => 'oauth']]); $this->client->getEmitter()->attach($oauth); // if app is in debug mode, we do logging if( App::make('config')['app']['debug'] ) { $this->addLogger(); } } private function addLogger(){ $log = new Logger('guzzle'); $log->pushHandler(new StreamHandler(__DIR__.'/../storage/logs/guzzle.log')); $subscriber = new LogSubscriber($log, Formatter::DEBUG); $this->client->getEmitter()->attach($subscriber); } }//class 

При работе с HTTP-запросами часто полезно иметь какую-то запись в журнал. Добавляем логирование, если приложение находится в режиме отладки.

Голосование на фотографиях

Если вы использовали веб-сайт 500px, вы можете увидеть, что у пользователя есть возможность голосовать за фотографии, чтобы повысить свой рейтинг. Мы можем получить список пользователей, которые проголосовали за определенную фотографию, и вы можете проголосовать за или против .

 // app/routes.php Route::post('/ajax/photo/vote', ['uses' => 'PXController@vote']); 
 // app/controllers/PXController.php public function vote(){ $photoId = Input::get("pid"); $px = App::make('pxoauth'); $url = "photos/{$photoId}/vote"; try { $result = $px->client->post($url, ["body" => ['vote' => '1']]); } catch(RequestException $e){ $response = $e->getResponse(); if($response->getStatusCode() === 403){ return (string) $response->getBody(); } return ["status" => 500, "error" => "A serious bug occurred."]; } return (string) $result->getBody(); } 
 // public/js/vote_favorite.js $('body').on('click', '.thumb .vote', function(e){ e.preventDefault(); $this = $(this); var pid = $this.parents(".thumb").data("photo-id"); $.ajax({ url: "/ajax/photo/vote", type: "POST", dataType: "json", data: { pid: pid }, success: function(data){ if(data.hasOwnProperty("error")){ alert(data.error); } else{ $this.text(data.photo.votes_count); alert("Photo voted successfully"); } } }); }); 

Лучший способ реализовать действие голосования — через AJAX. Мы собираемся отправить запрос на публикацию AJAX с идентификатором фотографии и получить ответ в формате JSON, который содержит сообщение об ошибке или обновленную фотографию.
После получения идентификатора фотографии мы отправляем запрос на photos/photo_id/vote конечную точку photos/photo_id/vote вместе с параметром vote (0 или 1). Если запрос не был успешным, мы можем перехватить исключение и проверить $response->getStatusCode() . Вы можете посетить документы, чтобы увидеть список ошибок.

Пометка фотографий как избранных

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

 // app/routes.php Route::post('/ajax/photo/favorite', ['uses' => 'PXController@favorite']); 
 // app/controllers/PXController.php public function favorite(){ $photoId = Input::get("pid"); $px = App::make('pxoauth'); $url = "photos/{$photoId}/favorite"; try { $result = $px->client->post($url); } catch(RequestException $e){ $response = $e->getResponse(); if($response->getStatusCode() === 403){ return (string) $response->getBody(); } return ["status" => 500, "error" => "A serious bug occurred."]; } return (string) $result->getBody(); } 
 // public/js/vote_favorite.js $('body').on('click', '.thumb .favorite', function(e){ e.preventDefault(); $this = $(this); var pid = $this.parents(".thumb").data("photo-id"); $.ajax({ url: "/ajax/photo/favorite", type: "POST", dataType: "json", data: { pid: pid }, success: function(data){ if(data.hasOwnProperty("error")){ alert(data.error); } else{ $this.text(data.photo.favorites_count); alert("Photo favourited successfully"); } } }); }); 

Если вы уже проголосовали или добавили фотографию в избранное, вы получите сообщение об ошибке ( Sorry, you have already voted for this Photo ). Этого можно избежать, отключив ссылку, если для атрибута voted или favorited в объекте фотографии установлено значение true .

Комментарии

Системы комментирования являются обязательными для пользователей, чтобы высказать свое мнение. API 500px предоставляет конечные точки для работы с комментариями. Мы разделили процесс на три основные части.

Одиночные фотографии

В первой части, когда пользователь нажал на фотографию, мы открыли ссылку на веб-сайте 500px. Теперь мы собираемся реализовать нашу собственную страницу с фотографиями.

photos/:photo_id точка photos/:photo_id принимает список параметров и возвращает выбранное фото или не найденную ошибку.

 // app/routes.php Route::get('/photo/{id}', ['uses' => 'PXController@show']); 
 // app/controllers/PXController.php public function show($id){ $px = App::make('pxoauth'); try { $photo = $px->client->get("photos/{$id}?image_size=4")->json(); return View::make('single', ['photo' => $photo['photo']]); } catch(RequestException $e){ $response = $e->getResponse(); if($response->getStatusCode() === 404){ // handle 404: photo not found } } } 
 // app/views/single.blade.php ... <h1>{{ $photo['name'] }}</h1> <p class="lead"> by <a href="/user/{{ $photo['user']['id'] }}">{{ $photo['user']['username'] }}</a> </p> <hr> <p><span class="glyphicon glyphicon-time"></span> Posted on {{ $photo['created_at'] }}</p> <hr> <img class="img-responsive" src="{{ $photo['images'][0]['url'] }}" alt=""> <hr> @if($photo['description']) <p class="lead">{{ $photo['description'] }}</p> @endif <hr> ... 

Если запрос был успешным, мы передаем объект фотографии в представление, в противном случае мы перехватываем исключение и обрабатываем ошибку 404. Вы можете посетить документы для более подробной информации.

Получение комментариев

Получение комментариев может быть сделано двумя разными способами. Мы можем передать параметр comments одной конечной точке photos/:id?comments ( photos/:id?comments ) или использовать конечную точку photos/:id/comments .
Второй способ позволяет нам получать вложенные комментарии, что облегчает их печать. API ограничивает количество комментариев на запрос до 20, и вы можете использовать параметр page чтобы получить полный список.

 // app/controllers/PXController.php public function show($id){ $px = App::make('pxoauth'); try { $photo = $px->client->get("photos/{$id}?image_size=4")->json(); $comments = $px->client->get("photos/{$id}/comments?nested=true")->json(); return View::make('single', ['photo' => $photo['photo'], 'comments' => $comments['comments']]); } catch(RequestException $e){ $response = $e->getResponse(); if($response->getStatusCode() === 404){ // handle 404: photo not found } } } 
 // app/views/single.blade.php @foreach($comments as $comment) <div class="media"> <a class="pull-left" href="#"> <img class="media-object" src="{{ $comment['user']['userpic_url'] }}" alt=""> </a> <div class="media-body"> <h4 class="media-heading">{{ $comment['user']['username'] }} <small>{{ $comment['created_at'] }}</small> </h4> {{ $comment['body'] }} @if(count($comment['replies'])) @foreach($comment['replies'] as $ncomment) <div class="media"> <a class="pull-left" href="#"> <img class="media-object" src="{{ $ncomment['user']['userpic_url'] }}" alt=""> </a> <div class="media-body"> <h4 class="media-heading">{{ $ncomment['user']['username'] }} <small>{{ $comment['created_at'] }}</small> </h4> {{ $comment['body'] }} </div> </div> @endforeach @endif </div> </div> @endforeach 

Вложенные комментарии вставляются в массив replies , и мы можем разбивать комментарии на страницы с total_pages атрибута total_pages . Вы можете посетить документы, чтобы увидеть список доступных параметров.

Comments

Новый комментарий

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

 // app/views/single.blade.php <div class="well"> <h4>Leave a Comment:</h4> {{ Form::open(['url' => '/photo/comment', 'method' => 'post']) }} <input type="hidden" name="pid" value="{{ $photo['id'] }}"/> <div class="form-group"> <textarea name="comment" class="form-control" rows="3"></textarea> </div> <button type="submit" class="btn btn-primary">Submit</button> {{ Form::close() }} </div> 
 // app/routes.php Route::post('/photo/comment', ['uses' => 'PXController@comment']); 
 // app/controllers/PXController.php public function comment(){ $photoId = Input::get('pid'); $comment = Input::get('comment'); $px = App::make('pxoauth'); $result = $px->client->post("photos/{$photoId}/comments", ['body' => ['body' => $comment]])->json(); if($result['status'] != 200){ // handle 400: Bad request. } return Redirect::back(); } 

Метод получает идентификатор фотографии и тело комментария. Затем мы photos/:photo_id/comments запрос к конечной точке photos/:photo_id/comments который принимает только эти два параметра и возвращает код состояния 200, если комментарий был успешно опубликован. В противном случае мы обрабатываем ошибку 400 или 404. Вы можете проверить документы для более подробной информации.

New comment

Загрузка новых фотографий

При использовании пакета, такого как Guzzle , загрузка файлов становится простым процессом. API принимает много параметров, но мы будем использовать только name , description и файл фотографии. Вы можете посетить документы для получения полного списка параметров.

 // app/routes.php Route::get('/upload', ['uses' => 'PagesController@photoUpload']); Route::post('/photo/upload', ['as' => 'photo.upload', 'uses' => 'PXController@upload']); 
 // app/views/upload.blade.php <div class="row"> {{ Form::open(['route' => 'photo.upload', 'files' => true]) }} <div class="form-group"> {{ Form::label('name', 'Name: ') }} {{ Form::text('name', null, ['class' => 'form-control']) }} </div> <div class="form-group"> {{ Form::label('description', 'Description: ') }} {{ Form::textarea('description', null, ['class' => 'form-control']) }} </div> <div class="form-group"> {{ Form::label('photo', 'Upload a photo') }} {{ Form::file('photo', null, ['class' => 'form-control']) }} </div> {{ Form::submit('Upload', ['class' => 'btn btn-primary']) }} {{ Form::close() }} </div> 

Upload form

 // app/controllers/PXController.php public function upload(){ try { $px = App::make('pxoauth'); $result = $px->client->post('photos/upload', [ 'body' => [ 'name' => Input::get('name'), 'description' => Input::get('description'), 'file' => fopen(Input::file('photo')->getPathname(), 'r'), ] ])->json(); // you may want to pass a success message return Redirect::to("/photo/{$result['photo']['id']}"); } catch(RequestException $e){ $response = $e->getResponse(); if($response->getStatusCode() === 422){ // handle 422: Server error } } }//upload 

Если вы хотите загрузить некоторые данные через HTTP, вам нужно иметь дело с заголовками multipart/form-data читать содержимое файла и добавлять его в запрос. Подробнее об отправке файлов с помощью Guzzle вы можете прочитать здесь .

API возвращает код состояния 200 вместе с новой фотографией в случае успеха, в противном случае мы получаем ошибку 422, если формат файла не поддерживается и т. Д. Мы перенаправляем пользователя на страницу новой фотографии.

New photo

Вывод

API 500px обладает большей функциональностью, чем показано в этом руководстве. Вы можете проверить другие приложения для взлома API, чтобы получить представление о том, что возможно, и вы можете проверить репозиторий Github, чтобы проверить конечный результат. Дайте мне знать, что вы думаете в комментариях ниже.