- 投稿日:2020-05-20T21:26:47+09:00
LaravelでIntervention Imageを利用して画像のサイズ(容量)を下げる方法
利用シーン
Laravelで開発をしていて、サーバーに画像を沢山アップすることが想定されるとき。
背景
Intervention ImageはPHPで扱える画像処理のライブラリ。
blurをかけたり、縦横幅をリサイズしたり、回転させたりと多岐にわたる機能を実現している。
http://image.intervention.io/しかし, 画像の容量を1MB未満に抑えたい、という要求に対してストレートに応えてくれる機能はない。(もし見つけたらご教示ください)
他のライブラリを探すのも面倒なので、機能を組み合わせて自分で作ってしまえばいいやということで関数を作ってみました。
コード
/** * @param UploadedFile $img_file 画像ファイル(*今回はUploadedFileを利用) * @param string $path 画像の保存パス * @param int $quality 画像の解像度の初期設定 * @param int $size ここまで下げたいという画像サイズの値 */ public function compressImage(UploadedFile $img_file, string $path, int $quality, $size) { $image = Image::make($img_file); $image->save($path, $quality); // クオリティを下げた後のファイルサイズが十分下がっていなければもう一度関数を呼び出す $image = Image::make($path); if($image->filesize() > $size){ $quality -= 5; return $this->compressImage($img_file, $path, $quality, $size); } }解説
$image = Image::make($img_file); $image->save($path, $quality);画像ファイルを読み込み、save()メソッドで任意の解像度に下げて保存。
*ドキュメントにはデフォルトで90と書いてありますが80未満で設定しておくと吉。
http://image.intervention.io/api/save$image = Image::make($path); if($image->filesize() > $size){ $quality -= 5; return $this->compressImage($img_file, $path, $quality, $size); }保存した画像を改めて読み込み、
filesize()メソッドで画像のファイル容量を確認。
ファイル容量が設定したサイズ(1MBなら1024000を入力)よりも大きければ、
解像度を5低く設定してもう一度同じ関数を再帰的に呼び出す。使い方
この関数をヘルパ関数として登録して
hoge.php$file = $request->file('img'); $path = "your/path"; $quality = 80; $size = 1024000; $resized_img = compressImage($file, $path, $quality, $size);とすれば使えます。
終わりに
もし他に良い方法や改善できる箇所がありましたらご教示ください。
- 投稿日:2020-05-20T15:36:21+09:00
PHP初心者がMacでLaravelに挑む
(試験的に勉強兼ねて英語で書いてみた)
Goal
- To learn from the environment setup to the fundamental usage
- To create a To-do app with Laravel
Environment setup
0. Development environment
Mac OS Catalina 10.15.4
MacBook Air (13-inch, Mid 2013)1. Downloading & Installing
1.1. Choosing the version
Laravel 7 (the latest version as of May 2020)
PHP 7.3.11 (Laravel 7 requires above 7.2.5)1.2. Installing composer
Access the above website and click
Download
Execute these four lines on this webpage like:
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" $ php -r "if (hash_file('sha384', 'composer-setup.php') === 'e0012edf3e80b6978849f5eff0d4b4e4c79ff1609dd1e613307e16318854d24ae64f26d17af3ef0bf7cfb710ca74755a') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" $ php composer-setup.php $ php -r "unlink('composer-setup.php');"They mean that in order:
・ Download the installer to the current directory ・ Verify the installer SHA-384 ・ Run the installer ・ Remove the installerMove Composer
$ mv composer.phar /usr/local/bin/composerCheck if it succeeded
$ composer -V Composer version 1.10.6 2020-05-06 10:28:101.3. Installing Laravel
Create a project called
sample
, or what else you like.$ composer create-project --prefer-dist laravel/laravel sample1.4. Starting a server
Move into the directory you made and start a server.
$ cd sample $ php artisan serveTry to access your local server:
http://localhost:8000
on a web browser!
Congratulations!!
Creating a ToDo app
Now I start to create a ToDo app known as that is simple and easy to develop for even a beginner.
I referred to this website:
Laravelの知識ゼロから基本をマスターするチュートリアル | Awesome BlogReferences
- 投稿日:2020-05-20T13:37:43+09:00
Windows10 に PHP7+Laravel環境をDockerで構築
概要
掲題のとおり「Windows10 に PHP7+Laravel環境をDockerで構築」を、
↓こちらの神記事を参考に、初心者向けに解説していきます。「どうしてそういう設定を施すのか?」といったことは元記事が丁寧に説明して下さっているので、ここではとにかくローカルPC内にLaravelサーバを立ち上げるまでの手続きを駆け足でご紹介すると共に、Windows10でやると行きづまる所を補足しています。
私が試した環境
- Windows10 Pro 64bit版
- Docker Desktop for Windows - 2.3.0.2 (今回の手順中でインストールします)
- Git for Windows - 2.25.0.windows.1 (今回の手順中でインストールします)
- Make for Windows - 3.81 (今回の手順中でインストールします)
下準備編
いくつかのソフトウェアが必要なので、ダウンロード&インストールしましょう。
Docker, docker-compose(Docker Desktop for Windows)
↓こちらをご参考に。
※ ↑の記事内に記載していますが、Windows10のエディションやパソコンのCPUによる条件がありますので、ご注意下さい。
Git, Git-Bash(Git for Windows)
↓こちらからダウンロードしてインストールしましょう。
https://gitforwindows.org/Git for Windows を入れれば Git-Bash も一緒に入ります。
Git-Bash があれば、WindowsでもLinuxやMacと同じ作法のコマンド操作ができます。
(※完全に同じことができるわけではありません!一部だけです。)
今回はコマンド作業が必要なので、これを使います。make for Windows
元記事では
make
コマンドを使用されているので必要です。
(複雑なコマンドをショートカットのようにまとめるのに使用されています。)↓こちらからダウンロードしてインストールしましょう。
http://gnuwin32.sourceforge.net/packages/make.htmmakeコマンドがあるフォルダを環境変数
PATH
に追加しておく。どこからでも
make
コマンドを打てるようにしておきましょう。
手順は割愛しますが、代わりに↓こちらの記事を紹介させていただきます。makeコマンドがあるフォルダの場所は、デフォルトのインストール設定では↓です。
C:\Program Files (x86)\GnuWin32\binmake for Windows をインストールするときにインストール先フォルダをカスタマイズした場合は、↑を参考に探してみてください。
一部コマンドをwinpty経由で実行するよう設定する。
Gitインストール時、オプション
Use MinTTY
をONにした場合、この設定作業が必要です。
- Windowsにログオンしているユーザーのホームフォルダ(例:
C:\Users\山田太郎
)の中に.bashrc
という名前のテキストファイルを作ります。(すでに存在する場合は不要です。).bashrc
の中身に↓を追記して保存します。alias docker='winpty docker' alias docker-compose='winpty docker-compose' alias make='winpty make'Git-Bashに慣れている方は、vimコマンドなどで作業してももちろんOKです!
※ winptyは、Windowsへのコマンド指示をLinuxっぽいインターフェースでできるようにするラッパー的なソフトです。
ここでは、docker
、docker-compose
、make
コマンドだけ、自動的にwinpty経由で実行するよう設定をしています。
これをしないと、dockerコンテナの中に入って作業する系のコマンドが↓のようなエラーで失敗します。$ docker-compose exec app composer create-project --prefer-dist laravel/laravel . the input device is not a TTY. If you are using mintty, try prefixing the command with 'winpty'また
make
の中で実行されるコマンドもwinpty経由で実行させるにはmake
自体をwinpty経由で実行しなければダメなので、3行目でそのように設定しています。構築編
こちらは駆け足でザッと参ります。
一通り完了したら、ぜひ元記事も読んでみてください。Git-Bashを起動する。
適当なフォルダを作って移動する。
ソースコードをダウンロードして色々やるので、万が一汚れても大丈夫なフォルダを作ってそこで作業しましょう。
ここでは例として、Cドライブ直下にtempというフォルダを作ってそこに移動してます。cd /c mkdir temp cd temp元記事で公開されているソースコード一式をダウンロードする。
githubに公開されているので、gitコマンドを使ってダウンロードします。
このコマンドなら、githubアカウントを持ってなくてもダウンロードできるはず…git clone git://github.com/ucan-lab/docker-laravel.git余談ですが、セキュリティ的には https:// で始まるURLで
git clone
するのが推奨されているので、githubアカウントをお持ちであれば↓こちらのコマンドでもOKです。git clone https://github.com/ucan-lab/docker-laravel.git
make
コマンド向け設定ファイルが存在するフォルダに移動する。cd docker-laravel/infrastructure
LaravelサンプルWEBサイトを新規作成するコマンドを実行する。
make create-project数分かかるかも。
ずらーっと流れるログが↓のようになって止まったらOK。・ ・ ・ Discovered Package: laravel/tinker Discovered Package: nesbot/carbon Discovered Package: nunomaduro/collision Package manifest generated successfully. 32 packages you are using are looking for funding. Use the `composer fund` command to find out more! XXXXXX@XXXXX MINGW64 /c/temp/docker-laravel/infrastructure $LaravelサンプルWEBサイトにアクセスしてみる。
↓をWEBブラウザで開いてみてください。
http://127.0.0.1これはLaravelフレームワークを使って作られているサンプルWEBページで、それを動かすためのWEBサーバが自分のPC内で起動している証です。
お疲れ様でした。
この記事では端折った部分もあるので、ぜひ元記事も一読してみてください。
- 投稿日:2020-05-20T12:03:01+09:00
Laravel6.x + Vue.js(TypeScript)のSPAでページネーション付きのテーブル作成
冒頭
- 個人開発でLaravel6.x + Vue.js(TypeScript)のSPA作ったので一部抜粋
- CSSフレームワークはVuetify2を採用
- 環境構築については一旦スルーします
- ソースコード例はこちら
ディレクトリ構造
フロント側の構造のみ抜粋
resources/ts ├── App.vue ├── app.ts ├── components │ └── pages │ └── Search.vue ├── laravel-data-entity │ └── PaginateObject.d.ts ├── plugins │ └── http.ts ├── router.ts ├── types │ └── index.d.ts └── vue-data-entity └── DataObject.d.tsソースコード
型定義ファイル
- データベースのテーブルに用意してるテーブルの構造を定義する
resources/ts/vue-data-entity/DataObject.d.tsexport interface FileDataObject { id: number; hoge: string; }
- Laravelのページネーションオブジェクトを定義する
resources/ts/laravel-data-entity/PaginateObject.d.tsimport { DataObject } from "../vue-data-entity/FDataObject" export interface PaginateObject { current_page: number; data: DataObject[]; first_page_url: string; from: number; last_page: number; last_page_url: string; next_page_url: string; path: string; per_page: number; prev_page_url: string | null; to: number; total: number; }Vue Routerの設定
resources/ts/router.tsimport Vue from 'vue' import Router from 'vue-router' import Search from './components/pages/Search.vue' Vue.use(Router) const router = new Router({ mode: 'history', routes: [ { path: '/search', name: 'Search', component: Search, }, ] }); export default router;Axiosをラップしたプラグインを作る
resources/ts/plugins/http.tsimport _Vue from 'vue'; import axios from 'axios'; export default { install(Vue: typeof _Vue): void { const http = axios.create({ responseType: "json" }); Vue.prototype.$http = http; }, };プラグインをインストール、ルーターを設定
resources/ts/app.tsimport Vue from "vue"; import router from './router' import App from "./App.vue"; ~~省略~~ import http from './plugins/http'; Vue.use(http); ~~省略~~ new Vue({ router: router, render: h => h(App), ~~省略~~ }).$mount('#app')Vue側のソースコード例
resources/ts/components/pages/Search.vue<template> <v-content> <v-container fluid> <v-simple-table dense> <template v-slot:default> <thead> <tr> <th class="text-left">id</th> <th class="text-left">hoge</th> </tr> </thead> <tbody> <tr v-for="(item, index) in data" :key="index"> <td>{{ item.id }}</td> <td>{{ item.hoge }}</td> </tr> </tbody> </template> </v-simple-table> <v-pagination v-model="page" :length="pageLength"></v-pagination> </v-container> <v-overlay :value="overlay"> <v-progress-circular color="primary" indeterminate size="64"></v-progress-circular> </v-overlay> </v-content> </template> <script lang="ts"> import { DataObject } from "../../vue-data-entity/DataObject"; import { PaginateObject } from "../../laravel-data-entity/PaginateObject"; import { Vue, Component, Watch } from "vue-property-decorator"; import VueRouter from "vue-router"; import { AxiosError, AxiosResponse } from "axios"; // registerHooksを登録しないとbeforeRouteUpdateが定義できません Component.registerHooks(["beforeRouteUpdate"]); export default class Search extends Vue { data: FileDataObject[] = []; overlay: boolean = false; pageLength: number = 1; page: number = 1; /** * created */ public created() { this.search(); } /** * watch * ルーティングに反映するためにWatchを使います。 */ @Watch("page") onPageChanged() { this.$router .push({ name: "Search", query: { page: this.page.toString() } }) } /** * search */ public search() { this.page = isNaN(Number(this.$route.query.page)) ? 1 : Number(this.$route.query.page); this.overlay = true; Vue.prototype.$http .get( `/api/search?page=${this.page}` ) .then((res: AxiosResponse<PaginateObject>): void => { this.data = res.data.data; this.pageLength = res.data.last_page; this.overlay = false; }) .catch((error: AxiosError): void => { alert("検索実行時にエラーが発生しました"); this.overlay = false; }); } /** * beforeRouteUpdate * ルーティングが更新される毎に(this.pageが変更する毎に検索を実行します) */ public beforeRouteUpdate(to: VueRouter, from: VueRouter, next: any) { next(); this.search(); } } </script>resources/ts/App.vue<template> <v-app id="inspire"> <router-view /> </v-app> </template>Laravel側
APIのルーティングを定義
routes/api.phpRoute::get('search', 'Api\SearchController@search');APIのコントローラーでページネーションオブジェクトを返却する
app/Http/Controllers/Api/SearchController.php<?php namespace App\Http\Controllers\Api; use App\Data; //モデルを定義しといてね use App\Http\Controllers\Controller; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; class SearchController extends Controller { /** * * * @return */ public function search(Request $request) { return Data::select('id', 'hoge')->paginate(10); } }resources/views/index.blade.php<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# website: http://ogp.me/ns/website#"> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="robots" content="index,follow"> <title>~~~~</title> </head> <body> <div id="app" > </div> <script src="{{ mix('/js/app.js') }}"></script> </body> </html>動作例
- 投稿日:2020-05-20T02:31:20+09:00
Vue.js+TypeScript+Nuxt.js環境で、『Property 'XXX' does not exist on type 'CombinedVueInstance~'�』を解消するためのtips
はじめに
Vue.js+TypeScript+Nuxt.js環境におけるScriptの書き方には下記の3種類があります。
- Vue.extend(OptionsAPI)
- defineComponent(CompositionAPI)
- vue-property-decorator(ClassAPI)
https://typescript.nuxtjs.org/ja/cookbook/components/#template
今回は、Vue.extend(OptionsAPI)を使用している場合の『Property 'XXX' does not exist on type 'CombinedVueInstance~'』というエラーを解消するためのtipsをまとめたものです。
しばしば遭遇するエラーだと思われますが、記事が少ないので取り急ぎまとめることにしました。
そのため、記事の内容については追加と修正を随時していきます。どんな時に発生するか
Vue.js+TypeScriptでcomputed、watch、methodsなどを書いていて、TypeScriptの型推論が効かなくなった時に発生します。
解消方法
- 返り値と引数の型を定義する
- TypeScript標準の型で定義できない場合はInterface、Typeで定義する
- 強制的にエラーをなくす
基本的には1と2で解決しますが、状況によっては3を使う場面があるかもしれませんので、参考までに入れておきます。
1.返り値と引数の型を定義する
methods: { someMethod (arg: number): number { return arg }, }返り値については、TypeScriptの型推論が行われる仕様になっているのですが、今回のように型推論が効かずにエラーの原因になり得るということと、可読性の観点から定義しておくべきだと考えています。
引数はそもそも型推論が行われませんので定義しないと他のエラーにも引っ掛かります。【 型定義の参考記事 】
https://qiita.com/is_ryo/items/6fc799ba4214db61d8ab2.TypeScriptの標準の型で定義できない場合はinterface、typeで定義する
number、string、voidなどの標準の型では定義できない複雑なものに関しては、下記のようにtypeやinterfaceを使用することによって定義することができます。
export type Hoge = { name: string price: number ,,,,省略 } ,,,,省略 methods: { someMethod (arg: Hoge): Hoge { return arg }, }【 InterfaceとTypeの違いの参考記事 】
https://qiita.com/tkrkt/items/d01b96363e58a7df830e3.強制的にエラーをなくす
本質的な解決ではありませんが、下記の2つのように書くと解消することができます。
computed: { ① return (this as any).hoge.method() ② // @ts-ignore return this.hoge.method() }①は(this as any)でany型にキャストすることができます。
②はts-ignoreによって次の行の型検査をスキップすることができます。
最後に
この他にも型定義関連のエラーは多々ありますので、随時投稿してまいります。
ナレッジを共有していって開発を効率化させましょう!
- 投稿日:2020-05-20T02:15:17+09:00
Laravelのmiddleware追加方法
0, なんでこの記事を書くか
「なんでこの記事を書くか」、、、
微妙に躓いたからです。1, やりたいこと
usersテーブル:levelsテーブル = 多:一
の関係があり、levelテーブルの特定のカラムの値が特定だった時に、特定のルートを有効化したい。実例
リレーション先のlevelsテーブルにadministorのカラムがあり、そのカラムの値が「true」のときに、
/settings
を見せたい。2, 解決策
> php artisan make:middleware Administorapp\Http\Middleware\Administor.php<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class Administor { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if(Auth::check()&&Auth::user()->level['administor']){ return $next($request); }else{ abort(403); } } }app\Http\Kernel<?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel extends HttpKernel { /*省略*/ protected $routeMiddleware = [ /*省略*/ 'administor' => \App\Http\Middleware\Administor::class, ]; }routes\web.php<?php use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Auth; /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::group(['middleware' => 'administor'], function () { Route::get('/settings', function(){ return view('pages.settings.index'); }); }); Auth::routes();
- 投稿日:2020-05-20T00:53:23+09:00
Laravel Commandを実装する(超初歩)
目的
- Laravelにてコマンドを作成する方法をまとめる
実施環境
- ハードウェア環境(下記の二つの環境で確認)
項目 情報 OS macOS Catalina(10.15.3) ハードウェア MacBook Pro (16-inch ,2019) プロセッサ 2.6 GHz 6コアIntel Core i7 メモリ 16 GB 2667 MHz DDR4 グラフィックス AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB
- ソフトウェア環境
項目 情報 備考 PHP バージョン 7.4.3 Homwbrewを用いて導入 Laravel バージョン 7.0.8 commposerを用いて導入 MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いて導入 概要
- ターミナルに「Test」と文字列を出力するだけのLaravelコマンドを作成する。
- コマンド名は「app:test」とする。
- クラスの作成
- コマンドの内容の実行内容記載
- 確認
詳細
クラスの作成
アプリ名ディレクトリで下記コマンドを実行してクラスを作成する。(クラスの命名方法はキャメルケースを用いる)
$ php artisan make:command TestCommand下記にクラスが記載されているファイル「TestCommand.php」が作成されている事を確認する。
アプリ名ディレクトリ/app/Console/Commands
コマンドの内容の実行内容記載
アプリ名ディレクトリで下記コマンドを実行してクラスが記載されているファイルを開く。
$ vi app/Console/Commands/TestCommand.php開いたクラスファイルを下記の様に修正する。
<?php namespace App\Console\Commands; use Illuminate\Console\Command; class TestCommand extends Command { /** * The name and signature of the console command. * * @var string */ // protected $signature = 'command:name'; //上記の行をコメントアウト、もしくは削除して下記の行を追加 protected $signature = 'app:test'; /** * The console command description. * * @var string */ // protected $description = 'Command description'; //上記の行をコメントアウト、もしくは削除して下記の行を追加 protected $description = 'ターミナル上に"Test"と出力するコマンド'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { //下記を追加 $this->info('Test'); } }確認
アプリ名ディレクトリで下記コマンドを実行して現在使用可能なコマンドの一覧を表示する。
$ php artisan list先のコマンドを出力結果の中に下記の記載が存在する事を確認する。
app app:test コマンドの実装方法を確認するコマンドアプリ名ディレクトリで下記コマンドを実行してターミナル上に「Test」と出力される事を確認する。
$ php artisan app:test Test