20200520のlaravelに関する記事は7件です。

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);

とすれば使えます。

終わりに

もし他に良い方法や改善できる箇所がありましたらご教示ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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

Composer
laravel1.png

Access the above website and click Download

laravel2.png

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 installer

Move Composer

$ mv composer.phar /usr/local/bin/composer

Check if it succeeded

$ composer -V
Composer version 1.10.6 2020-05-06 10:28:10

1.3. Installing Laravel

Create a project called sample, or what else you like.

$ composer create-project --prefer-dist laravel/laravel sample

1.4. Starting a server

Move into the directory you made and start a server.

$ cd sample
$ php artisan serve

Try to access your local server: http://localhost:8000 on a web browser!
laravel3.png

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 Blog

References

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Windows10 に PHP7+Laravel環境をDockerで構築

概要

掲題のとおり「Windows10 に PHP7+Laravel環境をDockerで構築」を、
↓こちらの神記事を参考に、初心者向けに解説していきます。

最強の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)

↓こちらをご参考に。

Windows 10 に 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.htm

makeコマンドがあるフォルダを環境変数PATHに追加しておく。

どこからでもmakeコマンドを打てるようにしておきましょう。
手順は割愛しますが、代わりに↓こちらの記事を紹介させていただきます。

Windows で環境変数 PATH をいじる方法のまとめ

makeコマンドがあるフォルダの場所は、デフォルトのインストール設定では↓です。

C:\Program Files (x86)\GnuWin32\bin

make for Windows をインストールするときにインストール先フォルダをカスタマイズした場合は、↑を参考に探してみてください。

一部コマンドをwinpty経由で実行するよう設定する。

Gitインストール時、オプションUse MinTTYをONにした場合、この設定作業が必要です。

  1. Windowsにログオンしているユーザーのホームフォルダ(例: C:\Users\山田太郎)の中に.bashrcという名前のテキストファイルを作ります。(すでに存在する場合は不要です。)
  2. .bashrcの中身に↓を追記して保存します。
alias docker='winpty docker'
alias docker-compose='winpty docker-compose'
alias make='winpty make'

Git-Bashに慣れている方は、vimコマンドなどで作業してももちろんOKです!

※ winptyは、Windowsへのコマンド指示をLinuxっぽいインターフェースでできるようにするラッパー的なソフトです。
ここでは、dockerdocker-composemakeコマンドだけ、自動的に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を起動する。

image.png

適当なフォルダを作って移動する。

ソースコードをダウンロードして色々やるので、万が一汚れても大丈夫なフォルダを作ってそこで作業しましょう。
ここでは例として、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

↓こういうWEBページが表示されたら、成功!
image.png

これはLaravelフレームワークを使って作られているサンプルWEBページで、それを動かすためのWEBサーバが自分のPC内で起動している証です。

お疲れ様でした。

:thumbsup::thumbsup::thumbsup:

この記事では端折った部分もあるので、ぜひ元記事も一読してみてください。

最強のLaravel開発環境をDockerを使って構築する【新編集版】

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.ts
export interface FileDataObject {
  id: number;
  hoge: string;
}
  • Laravelのページネーションオブジェクトを定義する
resources/ts/laravel-data-entity/PaginateObject.d.ts
import { 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.ts
import 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.ts
import _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.ts
import 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.php
Route::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>

動作例

n9o60-s67f1.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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の型推論が効かなくなった時に発生します。

解消方法

  1. 返り値と引数の型を定義する
  2. TypeScript標準の型で定義できない場合はInterface、Typeで定義する
  3. 強制的にエラーをなくす

基本的には1と2で解決しますが、状況によっては3を使う場面があるかもしれませんので、参考までに入れておきます。

1.返り値と引数の型を定義する

methods: {
  someMethod (arg: number): number {
    return arg
  },
}

返り値については、TypeScriptの型推論が行われる仕様になっているのですが、今回のように型推論が効かずにエラーの原因になり得るということと、可読性の観点から定義しておくべきだと考えています。
引数はそもそも型推論が行われませんので定義しないと他のエラーにも引っ掛かります。

【 型定義の参考記事 】
https://qiita.com/is_ryo/items/6fc799ba4214db61d8ab

2.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/d01b96363e58a7df830e

3.強制的にエラーをなくす

本質的な解決ではありませんが、下記の2つのように書くと解消することができます。

computed: {
  ① return (this as any).hoge.method()

  ② // @ts-ignore
  return this.hoge.method()
}

①は(this as any)でany型にキャストすることができます。

②はts-ignoreによって次の行の型検査をスキップすることができます。

最後に

この他にも型定義関連のエラーは多々ありますので、随時投稿してまいります。
ナレッジを共有していって開発を効率化させましょう!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelのmiddleware追加方法

0, なんでこの記事を書くか

「なんでこの記事を書くか」、、、
微妙に躓いたからです。

1, やりたいこと

usersテーブル:levelsテーブル = 多:一
の関係があり、levelテーブルの特定のカラムの値が特定だった時に、特定のルートを有効化したい。

実例

リレーション先のlevelsテーブルにadministorのカラムがあり、そのカラムの値が「true」のときに、/settingsを見せたい。

2, 解決策

> php artisan make:middleware Administor
app\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();

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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」とする。
  1. クラスの作成
  2. コマンドの内容の実行内容記載
  3. 確認

詳細

  1. クラスの作成

    1. アプリ名ディレクトリで下記コマンドを実行してクラスを作成する。(クラスの命名方法はキャメルケースを用いる)

      $ php artisan make:command TestCommand
      
    2. 下記にクラスが記載されているファイル「TestCommand.php」が作成されている事を確認する。

      • アプリ名ディレクトリ/app/Console/Commands
  2. コマンドの内容の実行内容記載

    1. アプリ名ディレクトリで下記コマンドを実行してクラスが記載されているファイルを開く。

      $ vi app/Console/Commands/TestCommand.php
      
    2. 開いたクラスファイルを下記の様に修正する。

      <?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');
          }
      }
      
  3. 確認

    1. アプリ名ディレクトリで下記コマンドを実行して現在使用可能なコマンドの一覧を表示する。

      $ php artisan list
      
    2. 先のコマンドを出力結果の中に下記の記載が存在する事を確認する。

      app
       app:test             コマンドの実装方法を確認するコマンド
      
    3. アプリ名ディレクトリで下記コマンドを実行してターミナル上に「Test」と出力される事を確認する。

      $ php artisan app:test
      Test
      
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む