- 投稿日:2019-07-07T21:08:40+09:00
【Laravel】Vue.jsでFile APIを使って画像プレビューを行なう方法
画像プレビューを実装
今回のゴールはこちら。
File API
File APIについて
ローカルで選択した File情報を取得できます。ただし、File APIを使わなくても以下の項目は普通に取得できます。
更新日時
ファイル名
データサイズ(バイト数)
MIMEタイプ(ファイルの種類)コード
sample.php<div id="imgview"> <img-view></img-view> </div>使用するVueをコンポーネントとして登録。
app.jsVue.component('img-upload', require('./components/ImgView.vue').default);ImgView.vue<template> <label for="file-sample"> <div class="drop"> <input class="input" id="file-sample" type="file" name="user_img" @change="onFileChange"> <i aria-hidden="true" class="fas fa-plus fa-7x"></i> <img class="img" id="file-preview" v-show="uploadedImage" :src="uploadedImage"> </div> </label> </template> <script> export default { data() { return { uploadedImage: "", }; }, methods: { onFileChange(e) { let files = e.target.files; this.createImage(files[0]); //File情報格納 }, //アップロードした画像を表示 createImage(file) { let reader = new FileReader(); //File API生成 reader.onload = (e) => { this.uploadedImage = e.target.result; }; reader.readAsDataURL(file); }, }, } </script>inputタグに
@changeを、imgタグにv-showを使います。
v-showに設定しているuploadedImageはimgタグのsrcにも設定されていて、uploadedImageにFile情報が入ると同時にsrcにもソースとしてFile情報が格納され表示されると言う仕組みです。なので最初の時点では何も入っておらず、v-showはfalseになるので
display: none;が適用されています。methods
onFileChangeでは選択されたFile情報を変数に格納。
files[0]を引数にcreateImage()メソッドを呼び出します。
ここでは、FileReaderときうオブジェクトを生成します。
onloadは正常にファイルを読み込んだときに発生するイベントです。
この中でuploadedImageに event.target.resultのデータを格納。
event.target.resultには画像データをテキストデータにしたものが入っています。
※これをData URIをスキーム化させると言うみたいです。最後にreadAsDataURL()で画像の読み込みを実行します。
- 投稿日:2019-07-07T19:15:49+09:00
LaravelでAPIを作成して、ReactのJSXにそのデータを表示したい
開発環境
- laravel 5.8
- docker
dockerは、LaradockでLaravel+Docker環境構築(mac)の方法で環境構築しました。
概要
LaravelでReactを使用できる方法から、Apiを作成してReactのJSXで表示したい
Reactへ切り替え
laravelのあるディレクトリへ移動
$ cd projectvue.jsからreactへ切り替え
$ php artisan preset react React scaffolding installed successfully. Please run "npm install && npm run dev" to compile your fresh scaffolding.npmをインストール
$ npm installJSファイルの保存を監視とビルドのため実行(control+cで終了)
$ npm run watchreactに切り替わっているか確認
resources/js/componentsがExample.vueからExample.jsになっていれば成功Example.js編集
Example ComponentをReactに変更
Example.jsimport React, { Component } from 'react'; import ReactDOM from 'react-dom'; export default class Example extends Component { render() { return ( <div className="container"> <div className="row justify-content-center"> <div className="col-md-8"> <div className="card"> <div className="card-header">React</div> <div className="card-body">I'm an example component!</div> </div> </div> </div> </div> ); } } if (document.getElementById('example')) { ReactDOM.render(<Example />, document.getElementById('example')); }次にwelcome.blade.phpのbodyタグを下記のように修正する。
id=exampleの要素から、Exampleがクラスが呼び出される。
welcome.blade.php<body> <div id="example"></div> <script src="{{mix('js/app.js')}}" ></script> </body>localhostでアクセスすると修正した内容が反映されています。
LaravelをApiとして使う準備
非同期で処理できるようにしたので、laravelをapi化します。今回はapp/Http/Controllers/api配下にPostControllerを作成します。
$ php artisan make:controller api/PostControllerapiのルーティングは、route/api.phpがあるので、以下のように記述します。
route/api.phpRoute::group(['middleware' => ['api']], function() { Route::resource('post' , 'api\PostController'); });modelとmigration作成
$ php artisan make:model Post -m中身はcontentカラムを追加します
public function up() { Schema::create('posts', function (Blueprint $table) { $table->bigIncrements('id'); // name,contentカラム追加 $table->string('name'); $table->text('content'); $table->timestamps(); }); }シーダーの作成
$ php artisan make:seeder PostsTableSeederpublic function run() { \DB::table('posts')->insert([ [ 'name' => '名前1', 'content' => '内容1' ], [ 'name' => '名前2', 'content' => '内容2' ], [ 'name' => '名前3', 'content' => '内容3' ], ]); }database/seeds/DatabaseSeederにPostsTableSeederを追記して
public function run() { $this->call(PostsTableSeeder::class); }マイグレーションとシーダーを実行
$ php artisan migrate --seedPostControllerのindexで作成したPostモデルを、jsonで返す
PostController.phppublic function index() { $posts = Post::all(); return response()->json($posts, 200); }本来なら、postman等のツールで確認しますが、今回はブラウザでhttp://localhost/api/posts
を直接叩いて、jsonで帰ってきたら成功react側でapiの利用
先ほど作成したPostモデルのデータをaxiosを使ってreact側で受け取ります。
axiosは、HTTPリクエストを送信するメソッドです。
今回はGETリクエストを送信します。Example.jsを下記のように修正します。
Example.jsimport React, { Component } from 'react'; import ReactDOM from 'react-dom'; import axios from 'axios'; export default class Example extends Component { constructor() { super(); this.state = { posts: [] }; } componentDidMount() { axios .get('/api/posts') .then(response => { this.setState({posts: response.data}); }) .catch(() => { console.log('通信に失敗しました'); }); } renderPosts() { return this.state.posts.map(post => { return ( <li key={post.key}> {post.name}: {post.content} </li> ); }); } render() { return ( <div className="container"> <ul> {this.renderPosts()} </ul> </div> ); } } if (document.getElementById('example')) { ReactDOM.render(<Example />, document.getElementById('example')); }まず初めconstructorのstateに、取得するpostsを格納する為に、空配列を用意します。
constructor() { super(); this.state = { posts: [] }; }次に、コンポーネントがマウントされた直後に呼ばれるcomponentDidMountにaxiosを記述して、stateの中にapiから取得したpostsを格納します。例外処理は、コンソールでエラーを返すようにします。
componentDidMount() { axios .get('/api/posts') .then(response => { this.setState({posts: response.data}); }) .catch(() => { console.log('通信に失敗しました'); }); }最後に、renderPostsメソッドで配列をループして、JSXでこのメソッドを呼び出します。
renderPosts() { return this.state.posts.map(post => { return ( <li key={post.key}> {post.name}: {post.content} </li> ); }); } render() { return ( <div className="container"> <ul> {this.renderPosts()} </ul> </div> ); }これで、laravelでreactのセットアップから、apiからデータを取得して、jsxで表示するところまでできました。
以上です。
次回は、Reduxの導入でもしたいと思っています。
- 投稿日:2019-07-07T19:15:49+09:00
LaravelでAPIを作成して、Reactで取得したい
開発環境
- laravel 5.8
- docker
dockerは、LaradockでLaravel+Docker環境構築(mac)の方法で環境構築しました。
概要
LaravelでReactを使用できる方法から、Apiを作成してReactのJSXで表示したい
Reactへ切り替え
laravelのあるディレクトリへ移動
$ cd projectvue.jsからreactへ切り替え
$ php artisan preset react React scaffolding installed successfully. Please run "npm install && npm run dev" to compile your fresh scaffolding.npmをインストール
$ npm installJSファイルの保存を監視とビルドのため実行(control+cで終了)
$ npm run watchreactに切り替わっているか確認
resources/js/componentsがExample.vueからExample.jsになっていれば成功Example.js編集
Example ComponentをReactに変更
Example.jsimport React, { Component } from 'react'; import ReactDOM from 'react-dom'; export default class Example extends Component { render() { return ( <div className="container"> <div className="row justify-content-center"> <div className="col-md-8"> <div className="card"> <div className="card-header">React</div> <div className="card-body">I'm an example component!</div> </div> </div> </div> </div> ); } } if (document.getElementById('example')) { ReactDOM.render(<Example />, document.getElementById('example')); }次にwelcome.blade.phpのbodyタグを下記のように修正する。
id=exampleの要素から、Exampleがクラスが呼び出される。
welcome.blade.php<body> <div id="example"></div> <script src="{{mix('js/app.js')}}" ></script> </body>localhostでアクセスすると修正した内容が反映されています。
LaravelをApiとして使う準備
次に、laravelをapi化します。今回はapp/Http/Controllers/api配下にPostControllerを作成します。
$ php artisan make:controller api/PostControllerapiのルーティングは、route/api.phpがあるので、以下のように記述します。
route/api.phpRoute::group(['middleware' => ['api']], function() { Route::resource('post' , 'api\PostController'); });modelとmigration作成
$ php artisan make:model Post -m中身はname、contentカラムを追加します
public function up() { Schema::create('posts', function (Blueprint $table) { $table->bigIncrements('id'); // name,contentカラム追加 $table->string('name'); $table->text('content'); $table->timestamps(); }); }シーダーの作成
$ php artisan make:seeder PostsTableSeederpublic function run() { \DB::table('posts')->insert([ [ 'name' => '名前1', 'content' => '内容1' ], [ 'name' => '名前2', 'content' => '内容2' ], [ 'name' => '名前3', 'content' => '内容3' ], ]); }database/seeds/DatabaseSeederにPostsTableSeederを追記して
public function run() { $this->call(PostsTableSeeder::class); }マイグレーションとシーダーを実行
$ php artisan migrate --seedPostControllerのindexで作成したPostモデルを、jsonで返す
PostController.phppublic function index() { $posts = Post::all(); return response()->json($posts, 200); }本来なら、postman等のツールで確認しますが、今回はブラウザでhttp://localhost/api/posts
を直接叩いて、jsonで帰ってきたら成功react側でapiの利用
先ほど作成したPostモデルのデータをaxiosを使ってreact側で受け取ります。
axiosは、HTTPリクエストを送信するメソッドです。
今回はGETリクエストを送信します。Example.jsを下記のように修正します。
Example.jsimport React, { Component } from 'react'; import ReactDOM from 'react-dom'; import axios from 'axios'; export default class Example extends Component { constructor() { super(); this.state = { posts: [] }; } componentDidMount() { axios .get('/api/posts') .then(response => { this.setState({posts: response.data}); }) .catch(() => { console.log('通信に失敗しました'); }); } renderPosts() { return this.state.posts.map(post => { return ( <li key={post.key}> {post.name}: {post.content} </li> ); }); } render() { return ( <div className="container"> <ul> {this.renderPosts()} </ul> </div> ); } } if (document.getElementById('example')) { ReactDOM.render(<Example />, document.getElementById('example')); }まず初めconstructorのstateに、取得するpostsを格納する為に、空配列を用意します。
constructor() { super(); this.state = { posts: [] }; }次に、コンポーネントがマウントされた直後に呼ばれるcomponentDidMountにaxiosを記述して、stateの中にapiから取得したpostsを格納します。例外処理は、コンソールでエラーを返すようにします。
componentDidMount() { axios .get('/api/posts') .then(response => { this.setState({posts: response.data}); }) .catch(() => { console.log('通信に失敗しました'); }); }最後に、renderPostsメソッドで配列をループして、JSXでこのメソッドを呼び出します。
renderPosts() { return this.state.posts.map(post => { return ( <li key={post.key}> {post.name}: {post.content} </li> ); }); } render() { return ( <div className="container"> <ul> {this.renderPosts()} </ul> </div> ); }これで、laravelでreactのセットアップから、apiからデータを取得して、jsxで表示するところまでできました。
以上です。
次回は、Reduxの導入でもしたいと思っています。
- 投稿日:2019-07-07T10:19:56+09:00
Laravelでコントローラーからviewへの変数の受け渡しについてメモ
Laravelの勉強がてらメモ。
viewヘルパ関数
Laravelでコントローラーからviewへ変数を渡す方法としては、
$data = array( "name" => "Tanaka", "age" => 30, ); return view('user', $data);viewヘルパ関数を使用。
第1引数は、
resources/viewsディレクトリ配下のファイル名。ちなみに
resources/viewsディレクトリ配下にディレクトリを作成し、その中にファイルを作成している場合は、ドットでつなぐ。resources/views/admin/user.phpの場合$data = array( "name" => "Tanaka", "age" => 30, ); return view('admin.user', $data);第2引数に配列を設定することで、ビューに変数を渡すことが可能。
withメソッドを使用
他のやり方としては、
withメソッドで変数を渡すこともできる。return view('admin.user')->with('name', 'Tanaka');compact関数を使用
compact関数を使用すると、もっと楽に変数をビューに渡せる。$name = "Tanaka"; $age = 30; return view('user', compact("name", "age"));compact関数ってLaravel特有の関数かと思いこんでましたけど、
普通にPHPの関数でした。https://php.net/manual/ja/function.compact.php
compact関数の結果を試しに出力。
$name = "Tanaka"; $age = 30; var_dump(compact("name", "age"));出力結果array(2) { ["name"]=> string(6) "Tanaka" ["age"]=> int(30) }やってることは、
$data = array( "name" => "Tanaka", "age" => 30, ); return view('user', $data);と同じですね。納得。
誰かスマートな書き方をした人のコードが広まったんだろうなぁ。
- 投稿日:2019-07-07T01:04:08+09:00
作成したLaravelコンテナを軽量化する
どうも、若松です。
前回はDockerでLaravelを起動するまでをまとめました。
https://qiita.com/t_wkm2/items/9b2011af9569627fee40しかしながら、現在のコンテナイメージはお世辞にも軽量とは言えません。
コンテナイメージサイズはコンテナ起動時間に直結するため、できるだけ軽量化していきたいと思います。Dockerfile
FROM amazonlinux:2 as vender # PHPインストール RUN amazon-linux-extras install -y php7.3 RUN yum install -y php-pecl-zip php-mbstring php-dom # Composerインストール RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" RUN php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" RUN php composer-setup.php RUN php -r "unlink('composer-setup.php');" RUN mv composer.phar /usr/local/bin/composer # 環境変数設定 ENV COMPOSER_ALLOW_SUPERUSER 1 ENV COMPOSER_HOME "/opt/composer" ENV PATH "$PATH:/opt/composer/vendor/bin" # Laravelインストール RUN composer global require "laravel/installer" # Laravelプロジェクト作成 WORKDIR /var/www RUN composer create-project laravel/laravel laravel FROM php:7.3-alpine # ビルド用コンテナから必要なコンテンツをコピー COPY --from=vender /opt/composer/vendor/ /opt/vender/ COPY --from=vender /var/www/ /var/www/ # ポートを公開 EXPOSE 8000 # Laravelサーバーを実行 WORKDIR /var/www/laravel CMD ["php","artisan","serve","--host","0.0.0.0"]軽量化に際して覚えておくこと
マルチステージビルド
マルチステージビルドは、一般的にビルドに必要なコンテンツの生成フェーズと実行に必要なコンテンツに絞ってコンテナを固めるフェーズに分けてコンテナをビルドすることを指します。
ビルド時に必要だが実行時にには必要ない(一般的にDeveloperKitのような)ものを実行するコンテナから除外できるため、コンテナイメージの軽量化が期待できます。squashオプション
Dockerfileでビルドする際、Step毎にコンテナのレイヤーが生成され、最終的なコンテナはそのレイヤーを含むためにサイズが肥大化しがちです。
ビルド時にsquashオプションを用いると、最終的にレイヤー1つに集約してくれるため、コンテナイメージの軽量化が期待できます。Alpine Linux
詳細は割愛しますが、軽量OSとしてコンテナ界隈では有名です。
https://ja.wikipedia.org/wiki/Alpine_LinuxAlpine Linuxをベースとすることで、その他のイメージをベースとするよりも、コンテナイメージの軽量化が期待できます。
Dockerfile詳細
ビルド用イメージ
FROM amazonlinux:2 as vender前回同様、AmazonLinux2をベースとしていますが、後段でしようするためにエイリアスとして
as venderを付けています。省略
# PHPインストール # Composerインストール # 環境変数設定 # Laravelインストール # Laravelプロジェクト作成 # ポートを公開 # Laravelサーバーを実行上記は前回と同じなため、解説を省略します。
実行用イメージ
FROM php:7.3-alpinePHP公式から提供されているAlpineLinuxのイメージを使用します。
これによってAlpineLinux且つPHP7.3の環境を構築できます。ビルド用コンテナから必要なコンテンツをコピー
COPY --from=vender /opt/composer/vendor/ /opt/vender/ COPY --from=vender /var/www/ /var/www/前段のビルド用コンテナから必要なコンテンツをコピーします。
ここで前段で用いた、as vender効力を発揮します。コンテナビルド
docker build -t laravel . --squashビルド時に
--squashオプションを付加します。
これによってレイヤーを1つに集約し、計量化を図ります。軽量化前と軽量化後の比較
軽量化前
docker images laravel REPOSITORY TAG IMAGE ID CREATED SIZE laravel latest xxxxxxxxxxxx xx seconds ago 748MB軽量化後
docker images laravel REPOSITORY TAG IMAGE ID CREATED SIZE laravel latest xxxxxxxxxxxx xx seconds ago 117MBまとめ
少しの工夫でコンテナが軽量化できることがわかっていただけたと思います。
最初にも述べたように、コンテナイメージサイズはコンテナ起動時間に直結するため、積極的に軽量化を図っていきたいですね。

