#何を作った?
PHP、laravelの勉強として、カバー画像も表示できるブックレビューアプリを作りました。
まずpaizaラーニングを参考に掲示板アプリを作り、そこにGoogleBooksAPIsでマンガのカバー画像を引っ張ってきます。
基本的な機能はよくある掲示板アプリと同様です。なのでAPIを利用した画像の取得・利用について書きます。
*検索の精度はかなり悪いです。
その他の機能についてはこちらで簡単にまとめました。
[laravelで作った画像も表示できるブックレビューの機能について ※ポートフォリオの解説です](https://qiita.com/Shogo_S/items/7c3273f99075c2d931ed)##レビューを投稿するまでの流れ(ログイン済みと想定)
①まず検索窓にマンガのタイトルを書きます。
②候補のカバー画像がいくつか出てきます。この画像はボタンになっていて、クリックして選択できます。
③画像を選択したらタイトルと本文を記入し、投稿して完成です。いいね!ボタンもあります。
僕は左側に画像、右にタイトルと本文を配置しました。
##検索フォームを作る
{{ Form::model(['route' => ['article.getCover']]) }}
<div class='form-group'>
{{ Form::label('bookName', 'Book name:') }}
{{ Form::text('bookName', null) }}
{{ Form::submit('検索する', ['class' =>'btn btn-primary'])}}
</div>
{{ Form::close() }}
<div class = 'form-group'>
<a href={{ route('article.new') }}>戻る</a>
</div>
bookNameはマンガのタイトル。下記のgetCoverメソッドに送る。
##GoogleBooksAPIsの導入
下記を参考にしました。
書籍検索APIはGoogleBooksAPIsがオススメ【導入も楽ちんです】
書籍検索APIであるGoogle Books APIsの使い方(PHPでのサンプルコードあり)
public function getCover(Request $request)
{
if($request->filled('bookName')){
$content= $request->bookName;
$data = "https://www.googleapis.com/books/v1/volumes?q=" .urlencode($content) ."&maxResults=10";
$json = file_get_contents($data);
$json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
$json_decode = json_decode($json,true);
}else {
$json_decode = [];
}
受け取ったbookNameは$contentに代入されます。
$dataはGoogleBooksAPIs。タイトル名をそのまま埋め込むと正しくエンコードされないので、urlencode()に入れます。
JSONデータの取得に関しては下記を参考にさせていただきました。
PHPでJSONデータの取得の仕方
変更点
##画像をボタンとして表示する
@if ($json_decode)
@foreach ($json_decode['items'] as $item)
<form style="height:200px;width:200px;float:left" action="{{action('ArticleController@create')}}" method="get">
<input type="hidden" value="{{ $item['volumeInfo']['imageLinks']['thumbnail'] }}" name="url">
<button type="submit"><img src = "{{ $item['volumeInfo']['imageLinks']['thumbnail'] }}" ></button>
</form>
@endforeach
@endif
ボタンを表示します。Formファザード は使っていません。foreachで複数件表示して、それぞれをボタンにします。
配列は入れ子になっていて、画像を表示するURLは$json_decode['items']の中の['volumeInfo']の中の['imageLinks']の中にある['thumbnail']に格納されています。複数件取得することができるのでforeachを使用しています(['items']以下が複数件取得できます)。
課題
この方法だと、配列が変化するとエラーになってしまいます。例えば、GoogleBooksAPIsを利用してJSONのデータを10件取得した場合、その中に配列['thumbnail']を含んでいないデータが一つでもある場合はエラーになってしまいます。いくつか方法は試したのですが、まだ解決できていません。public function create(Request $request)
{
$posts = $request->url;
$message = 'New article';
return view('new',['message' =>$message, 'posts' =>$posts]);
}
送られた画像URLを$postsに格納し、投稿編集画面に送ります。
##タイトルと本文を書く
<h1>edit review</h1>
<p>{{$message}}</p>
//下記に画像URL渡します。表示用。
<img src={{$posts}}>
//投稿フォーム
{{ Form::open(['route' =>'article.store'])}}
//下記にも画像URL渡します。まだ保存はされていないので、このフォームでPOSTしてデータベースに保存します。
<div class = 'form-group'>
{{ Form::hidden('url',$posts)}}
</div>
//レビューのタイトル。
<div class = 'form-group'>
{{ Form::label('title','Title:')}}
{{ Form::text('title', null)}}
</div>
//レビュー本文。
<div class = 'form-group'>
{{ Form::label('content','Content:')}}
{{ Form::text('content',null)}}
</div>
//このレビューを投稿するユーザー。このアプリではログインしたユーザーだけが投稿できます。
//投稿画面にアクセスできるということは、このユーザーは既にログインしていると言えます。
//なのでAuth::user()->nameを投稿者として、この記事のユーザー名にします。
<div class='form-group'>
{{ Form::label('user_name', Auth::user()->name) }}
{{ Form::hidden('user_name',Auth::user()->name ) }}
</div>
<div class = 'form-group'>
<a href={{ route('article.getCover') }}>画像検索</a>
</div>
<div class = 'form-group'>
{{ Form::submit('作成する', ['class' =>'btn btn-primary'])}}
<a href={{ route('article.list') }}>一覧に戻る</a>
</div>
{{ Form::close() }}
//フォームが空欄の場合はフラッシュメッセージを表示します。
@if (session('flash_message'))
<div class="flash_message">
{{ session('flash_message') }}
</div>
##ストアメソッドで保存する
public function store(Request $request, Article $article)
{
if($request->content != "" && $request->title !=""){
$article = new Article();
$user = \Auth::user();
$article->image_url = $request->url;
$article->title = $request->title;
$article->content = $request->content;
$article->user_name = $request->user_name;
$article->user_id = $user->id;
$article->save();
return redirect()->route('article.show',['id'=>$article->id]);
}else{
session()->flash('flash_message', '空欄を埋めてください');
return redirect()->back();
}
}
上記のstoreメソッドで保存し、$article->image_urlを表示するviewを作成します。
下記がルートになります。
//レビューのリスト。
Route::get('/articles','ArticleController@index')->name('article.list');
//検索ページに飛ぶ
Route::get('/article/getCover','PostController@getCover');
//書籍名を検索する
Route::post('/article/getCover','PostController@getCover')->name('article.getCover');
//選択した画像を編集画面にgetで送る。
Route::get('/article/new','ArticleController@create')->name('article.new');
//新規投稿のレビューをデータベースに保存する。
Route::post('/article', 'ArticleController@store')->name('article.store');
//投稿したレビューを表示する。
Route::get('/article/{id}','ArticleController@show')->name('article.show');
//レビューを削除する
Route::delete('/article/{id}','ArticleController@destroy')->name('article.delete');
//投稿したレビューを再び編集する
Route::get('/article/edit/{id}', 'ArticleController@edit')->name('article.edit');
//@editで編集したデータをポストして保存する
Route::post('/article/update/{id}', 'ArticleController@update')->name('article.update');
##課題 / 問題点
- マイグレーションでエラーが発生したため、下記URLを参考にCSRFの仕組みを無効化することで対処しています。なので参考にされる際は注意してもられると。CSRFの仕組みを理解するため、今は生のPHPで掲示板を制作しています。順番おかしいですね。
【Laravel】419のHTTPエラーが出た場合の対処法!
もっとわかりやすく書いた方がいいし、用語の使い方も修正した方がいいですよね。
もっと勉強して随時アップデートしたいです。