20200626のlaravelに関する記事は8件です。

Laravelで"have you enable the php_fileinfo extension?"のエラーでハマったときの解決法(WIN)

概要

laravelでアプリケーションを制作していて、画像ファイルのアップロードの際に
Unable to guess the MIME type as no guessers are available (have you enable the php_fileinfo extension?).
のエラーメッセージが出て解決するのに苦労した話を聞いてほしくて記事にする。
error.png

環境

OS: Windows10 バージョン1909
Laravel: 7.16.1
PHP: 7.4.1
開発環境にMAMPを使用

解決策

php.iniに
extension=php_fileinfo.dll
を追記する

解決までの奮闘記

まずはエラーメッセージの内容を把握(エラーメッセージで検索をかけるなどする)
どうもphp_fileinfoという拡張モジュールがないからMIME typeが推測できねぇ、おまえphp_fileinfo持ってる?
みたいなことを言われてるらしい

ほう

そこでphp_fileinfoで検索するといくつかの参考になりそうなサイトが出てきました。
【PHP】PHP extension(PHP拡張モジュール)の確認と有効化(ext-fileinfo、ext-gd編)
PHP: Fileinfo - Manual

記事の中では
php.iniというファイルにいる
;extension=php_fileinfo.dll
extension=php_fileinfo.dll こう
コメントを外して有効化しましょうということでした。

ですが、php初心者の私はphp.iniがどこにいるかわかりません。
php.ini どこphp.ini MAMPなどで検索して以下のような参考サイトを見つけました。

php.iniファイルの場所/PHPのバージョン確認・変更 - MAMPの使い方
もういい加減覚えよう。php.iniはどこにあるのか

記事によるとMAMPでOpen web start pageした後のphpinfoの中にphp.iniのありかが書かれているようでした。
私の場合は以下のような場所
image.png

よっしゃ見つけた。
と思って意気揚々とphp.iniを開いたのですが
いくら探せどphp_fileinfoという文字列が見つかりません。

fileinfoで検索したときはどこのサイトも
;extension=php_fileinfo.dll
extension=php_fileinfo.dll こう
と言ってます。ですがコメントを外そうにもそもそもないのだから始末が悪い
勝手に追記していいものか判断がつかなかったので、もう少し調べて見ることにしました。

いくつかのサイトやディレクトリを漁っているうちに
C:\MAMP\bin\php\php7.4.1\ext
の中にphp_fileinfo.dllがあるのを発見しました。
しかし上記php.iniの場所は
C:\MAMP\conf\php7.4.1\php.ini
であり微妙に違います。
ですが、MAMPのphpのバイナリはC:\MAMP\bin\php\php7.4.1\のなかにphp.exeがあるので
コンフィグファイルとバイナリが別の場所にいるだけで
コンフィグファイルに書いとけばphpがよしなにやってくれるのでは思い
C:\MAMP\conf\php7.4.1\php.ini の中に
extension=php_fileinfo.dll を追記しました。
image.png

そしてサーバー再起動し、いざ画像のアップロードを試したところ
無事アップロードできましたとさ
めでたしめでたし

あとがき

なぜphp.iniにphp_fileinfoの記載がなかったのか未だ謎ですが
phpのバージョンなのかMAMPが原因なのかわかりません。知っている方いたら教えてください。
phpが嫌いになるとこでした、無事解決してよかったです。
同じような不具合に悩まれてる方の助けになれば幸いです。

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

Laravel、シーディングの設定方法(基礎)

皆さんこんにちは:raised_hand:
今回はLaravelのシーディングについて解説していきます。
それでは早速いきましょう:point_up:

開発環境

・Mac
・php 7.4.6
・Laravel 7.15.0
・MySQL

シーディングとは

今回はシーディングの説明に重きを置きたいので、ModelやMigrationについての詳しい説明は割愛させて頂きます:pray:なので、シーディングの前にModelとMigrationを終わらせといてください。

シーディングとは、データーベースに始めから用意されているサンプルを作成する機能のことです。
シーディングにより作成されたレコードのことを、シードと呼びます。
掲示板などのアプリケーションをデプロイした時に、初期状態でサンプルが全く無いと寂しいですよね(笑)

シーディングの手順

データベースにpostsテーブルがあるとします。このテーブル内にシーディングによってサンプルを作れるようにしていきます。まずは、terminalで以下のコマンドを実行します。

1. $ php artisan make:seeder PostsTableSeeder

これによりdatabase/seeds内に、PostsTableSeeder.phpというファイルが作成されます。

PostsTableSeeder.phpのファイルは以下のような記述があります。

PostsTableSeeder.php
<?php
 use Illuminate\Database\Seeder;

class PostsTableSeeder extends Seeder
{
   public function run()
   {

   }
}

2. PostsTableSeeder.phpにコードを書いていく

postsテーブルにtitle,bodyのサンプルを作成していきます。

PostsTableSeeder.php
<?php
 use Illuminate\Database\Seeder;

class PostsTableSeeder extends Seeder
{
   public function run()
   {
      DB::table('posts')->insert([
        'title' =>  'タイトル。',
        'body' => 'テキスト。テキスト。テキスト。テキスト。テキスト。',
      ]);

      DB::table('posts')->insert([
        'title' =>  'タイトル。',
        'body' => 'テキスト。テキスト。テキスト。テキスト。テキスト。',
      ]);
   }
}

3. DatabaseSeeder.phpに登録

PostsTableSeeder.phpと同じ階層に、DatabaseSeeder.phpというファイルがあります。
DatabaseSeeder.phpは以下のように記述します。

DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;

   class DatabaseSeeder extends Seeder
   {
       public function run()
       {
           $this->call([
               PostsTableSeeder::class;   //追加した記述
           ]);
       }
   }
}

追加でコメントのシーダーを作成したい場合は、DBにcommentsテーブルを作成してpostsテーブルと同様にファイルを作成します。そして、DatabaseSeeder.phpのcallメソッド内に記述すればいいですね。以下のようになります。

DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;

   class DatabaseSeeder extends Seeder
   {
       public function run()
       {
           $this->call([
               PostsTableSeeder::class;   
               CommentsTableSeeder::class;  //追加した記述
           ]);
       }
   }
}

4. $php artisan db:seed

最後にこのコマンドを実行すれば、DBにサンプルのデータが作成されます。

気づいた人もいるかと思いますが、このやり方だとたくさんのデータを挿入するのは面倒ですよね。
そういう場合は、factoryを使います。今回は説明しませんので興味があるひとは是非調べて見てください:thumbsup:

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

Laravel v7で「Formクラスが無い」とエラーが出た時の対処法

formファサードを使おうと思ったら「Formクラスが無い」とゆうエラーがでた

そういえば手動でcomposer.jsonをいじらなきゃいけないことを思い出し、下記をcomposer.jsonに追加。

"require": {
        "laravelcollective/html": " 7.17.2"
    },

追加したら$ composer updateをする。

しかし下記のエラーが出る

Your requirements could not be resolved to an installable set of packages.
  Problem 1
    - Conclusion: remove laravel/framework v7.17.2
    - Conclusion: don't install laravel/framework v7.17.2
    - Conclusion: don't install laravel/framework v7.17.1
    - Conclusion: don't install laravel/framework v7.17.0
    - Conclusion: don't install laravel/framework v7.16.1
    - Conclusion: don't install laravel/framework v7.16.0
    - Conclusion: don't install laravel/framework v7.15.0
    - Conclusion: don't install laravel/framework v7.14.1
    - Conclusion: don't install laravel/framework v7.14.0
    - Conclusion: don't install laravel/framework v7.13.0
    - Conclusion: don't install laravel/framework v7.12.0
    - Conclusion: don't install laravel/framework v7.11.0
    - Conclusion: don't install laravel/framework v7.10.3
    - Conclusion: don't install laravel/framework v7.10.2
    以下省略

どうやらこの投稿日時点では"laravelcollective/html"のversionがlaravelのv7に対応していないみたい。。

解決としてはlaravelcollective/html"の最新versionを指定してあげれば解決する。

"require": {
        "laravelcollective/html": " 6.1.2"
    },

もう一度$ composer updateをする。
これでいけるはず。

あとは他の記事にもあるように、app.phpファイルに下記を追加。

   'providers' => [
        Collective\Html\HtmlServiceProvider::class,
    ],

    'aliases' => [
        'Form' => Collective\Html\FormFacade::class,
        'Html' => Collective\Html\HtmlFacade::class,
    ],

解決です。

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

【Laravel】Email Verification(メール確認)の実装

概要

一般的なアプリケーションで会員登録する場合、
 1. 仮登録する
 2. メールにURLが届く
 3. URLをクリックして登録が完了する
という流れがありますよね
これができるようにLaravelのファイルをいじっていきましょう

前提

Laravel6以上で行います
あらかじめAuth機能を使えるようにしておいてください

% composer require laravel/ui
% php artisan ui vue --auth
% npm install && npm run dev

また、メールが送れるようにconfig/mail.phpや.envファイルを変更しておいてください

方法

さすがLaravelさん、こういう時のためにちゃんと用意してあるんですね
なんと、いじるファイルはUser.phpとweb.phpの2つだけ
必要な手順は以下の通り

  • マイグレーション
  • User.phpの編集
  • web.phpの編集

マイグレーション

% php artisan migrate

を実行してください
すでに実行している場合は必要ありません
これによって、メール確認に必要なemail_verified_atカラムを含んだusersテーブルが作成されます

User.php

app/User.php
class User extends Authenticatable implements MustVerifyEmail

Userクラスにimplements MustVerifyEmailを追加してください
これに必要なuseはすでに書かれてあります(さすが)
これによって、メール確認に必要な処理(URL生成やメール送信など)が追加されます

web.php

routes/web.php
Auth::routes(['verify' => true]);

Auth::routes()の引数に['verify' => true]を追加してください
これによって、メール確認に関連するルーティングが使用されます

カスタマイズ

ページの保護

仮登録や本登録を行うということは、本登録したユーザーだけがアクセスできるページがあるわけです
middlewareにverifiedを指定することで、ルートを保護できます
例を以下に示します

routes/web.php
Route::get('welcome', function() {
        ......
    })->middleware('verified');

Route::group(['middleware' => ['auth', 'verified']], function() {
    Route::get('index', HelloController@index);
    // このようにして保護したいルートをここに書く
}

ビュー

必要なビューは前提で実行したコマンドによって、すでに生成されています
メール確認のビューはresources/views/auth/verify.blade.phpにあります
自分の好きなようにカスタマイズしましょう

確認後のリダイレクト

メールアドレスを確認した後、自動的に表示させるページがあるといいですよね
デフォルトでは'/home'にリダイレクトすることになっていますが、これを変更するにためには、VerificationController.phpのredirectToにリダイレクト先を指定してください

RouteServiceProvider.phpのHOMEを変更する手段もありますが、こちらは、他のところでRouteServiceProvider::HOMEを参照している部分も一緒に変更できます

app/Http/Controllers/Auth/VerificationController.php
protected $redirectTo = '/home';
app/Providers/RouteServiceProvider.php
public const HOME = '/home'

おわり

簡単でしたね
公式ドキュメントReadoubleを読めばいいので、ここで説明する必要なかったかもしれませんが、備忘録ということで書いてみました

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

初めてのLaravel+Vue.js

わたしの100のリスト

Laravelや、Vueを勉強中です。
それらのアウトプットを考えていたところ、家族から「シンプルなやることリストが欲しい!」という要望をもらったので、シンプルなToDoアプリを作成しました。

その時の制作日誌として、学びと反省点をまとめます。
今後学ぶ人たちのヒントになればと思います。

公開URL
https://wishlist100.herokuapp.com

背景、目的

市場には多くのToDoアプリがあるが、多くは短期的なToDoをこなすことを目的としている。

人生では長期的な目標を成し遂げることがとても重要であり、そのような人生でやりたいことに焦点を当てたToDoアプリ「私の100のリスト」を作成した。

類似アプリとの差別化

すでに本アプリのような長期的な目標、夢をリスト化するアプリはあるが、リストを複数作れたり、いくつも追加できたりして本当に重要なものが明確になりにくい。

そこで、本アプリではリストに登録できる項目は100個までとした。

また、やりたいことと、すでにやったことを別々に表示して、やりたいことに集中できるように、またやったことは歴史として振り返られるようにした。

スペック

  • 言語

    • PHP 7.3
    • JavaScript
  • フレームワーク

    • Laravel 5.8.38
    • Vue.js 2.5.17
  • サーバ

    • heroku

開発環境

  • MacBook Air
  • Homestead
  • VSCode

機能一覧

  • ユーザー登録
  • アカウント編集
  • 退会
  • ログイン
  • ログアウト
  • やりたいこと一覧表示
  • やったこと一覧表示
  • カテゴリ別表示
  • やりたいこと作成
  • やりたいこと編集
  • やりたいこと削除
  • 達成、未達成の切り替え

機能詳細

  • ユーザー登録
    • ユーザー名、Email、パスワードによりユーザーを登録する。
  • アカウント編集
    • ユーザー設定から、ユーザー名、Email、パスワードを変更する。
  • 退会
    • ユーザー設定から、退会ボタンの押下によりアラートを出し、OKであれば退会する。
    • 退会処理後は、トップページへ遷移する。
  • ログイン
    • ログイン画面でEmailとパスワードを入力しログインボタンの押下によりログインする。
  • ログアウト
    • ログアウトボタンの押下によりログアウトする。
  • やりたいこと一覧表示
    • やりたいことのリストを表示する。
    • 各項目には、カテゴリアイコン、内容、達成ボタン、登録日時を表示する。
    • 達成ボタンを押すと一覧から除外され、やったことリストに移動する。
  • やったことリスト
    • 達成したことをリストで表示する
    • 各項目には、カテゴリアイコン、内容、達成日時を表示する。
  • やりたいこと作成
    • 入力エリアにやりたいことを入力、カテゴリ一覧からアイコンを選択、登録ボタンの押下により、一覧へ追加する。
    • やりたいことが空で登録された場合、エラーを表示する。
    • やりたいことは30文字以内で入力する。
  • やりたいこと編集
    • やりたいことを押下により、やりたいこと、カテゴリを編集できる。
    • 変更ボタンの押下により、編集を終了し一覧を更新する。
  • やりたいこと削除
    • やりたいことを押下により、削除ボタンを表示する。
    • 削除ボタンの押下により、削除確認のアラートを出す。OKであれば一覧から削除する。
  • 達成、未達成の切り替え
    • 各やりたいことの達成ボタンを押下により、やったこと一覧へ移動する。
    • やったこと一覧において、Undoボタンの押下により、やりたいこと一覧へ移動する。

DB設計

  • Usersテーブル・・・LaravelのAuthで作成されたテーブルをそのまま採用。
    • id, name, email, email_verified_at, password, remember_token
  • Wishesテーブル
    • id, user_id
  • Itemsテーブル
    • id, list_id, category_id, text, done_flg
  • Categoriesテーブル
    • id, name

Users:Wishes = 1:1
Wishes:Items = 1:多
Items:Categories = 1:1

躓いた点、学び

1. bladeテンプレートでいくかVue.jsのコンポーネントでいくか悩んで手戻り発生

リストの表示、アイテムの追加、切り替え、削除などは、ページ遷移なしでSPA風に作った。

ただ、どこからどこまでシングルページのアプリとするか、できるところだけやってみるか、当初からどうするか迷っていた。

まずはbladeテンプレートで作ってみようという考えで作って、「モーダルで操作するならページ遷移しない方がよくない?」と、途中から方針変更。

その結果いろいろ作り直し。
最終的なコードももっとスマートな構成があるかも。

結論:方針をしっかり決めておくこと

結局、方針がしっかり定まっていなかったから。

モーダル使うなら使うでしっかり決めて、ページ遷移するところ、しないところしっかり決めること。

2. 本番環境で見ることは大事

herokuにアップして公開したが、ローカルではわからない、スマホで触ってみないと気づかない不具合が結構あり。

やりたいことの追加ボタンを押すと入力用のモーダルウインドウを表示するが、いざ入力しようとするとスマホの予測変換が被って入力範囲が見れない・・・。

モーダルの実装に問題があると思うが、これは開発環境じゃ見つけられなかった。
(ちなみに、入力順序を入れ替えて対応しているだけで、まだ根本解決できてません・・・)

結論:現地・現物・現場

三現主義は何にしても重要。

制作時間

ざっくりとした制作時間。
Laravelとvueの実装部分は、この作業はフロント側だなと感じたものを自己流に分けているだけで、何かを拠り所にしているわけではありません。

当初の見積もりに比べて、下記の原因で増加。

  • UIの部分で時間がかかった
  • 上記で挙げたbladeとvueの方針の部分でいろいろ悩んだ
  • Homesteadの環境構築も初めてで時間取られた
工程 見積もり (h) 実質 (h)
機能洗い出し 1 1.5
画面設計   3 3
DB設計 0.5 0.5
モック作成 6 11.5
環境構築 0.5 2
フロント側実装 20 21
サーバー側実装 10 15.5
テスト、デプロイ 5 3
合計 46 56

まとめ

荒削りではありますが、LaravelとVue.jsを使って、一通りのCRUD処理を使ったアプリを作成することができました。

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

【Laravel】UnitTest、FeatureTest、BrowserTestの違い

はじめに

Laravelにおいて、
テストコードは3種類存在します。

・UnitTest
・FeatureTest
・BrowserTest

この3つの違いがよく分からなかったので、
自分なりにしっくりくるように簡単に整理しました。

UnitTest

/tests/Unit配下にテストを配置する。
一番粒度の細かいテスト。

Service、Model、Middleware、Policyなど、
自分で作ったクラス1つ1つと対応するように
テストクラス(ファイル)を1つ1つ作る。

その対象クラスのメソッド1つ1つの動作を検証するための
テストケースをコードに書いていく。

Controllerクラスのテストは
UnitTestではなくFeatureTestとするほうがしっくりくる。

FeatureTest

/tests/Feature配下にテストを配置する。
UnitTestより粒度を大きくしたテスト。

1つのHTTPリクエスト単位の動きをテストする。
=ルーティング1つごとにテストクラス(ファイル)を作る
=コントローラのアクションメソッド単位でのテスト

UnitTestでテストした各クラスを結合した状態で
コントローラの動き(つまりリクエストを受けてレスポンスを返すまで)をテストするというイメージ。

1つのコントローラアクションに対応したテストクラス(ファイル)の中で、
・ログインした状態でアクセス時の動作
・未ログインアクセス時の動作
・検索パラメータ付けたアクセス時の動作
・ユーザに特定ロールを付けた状態の動作
など1つ1つのケースをテストケースとしてコードを書く。

BrowserTest

/tests/Browser配下にテストを配置する。

実際にブラウザを使って画面にリクエスト、
ボタンをクリック、
マウスホバー、
フォーム送信などの操作をするテストをコードで実行できる。

FeatureTestにさらに
・複数HTTPリクエストの遷移
・画面操作時のJsの動作
のような観点を加えてテストできるイメージ。

Unit、FeatureはPHPUnitで動作するテストなのに対し、
BrowserTestはlaravel/duskというパッケージを使ったテスト。

参考

https://readouble.com/laravel/7.x/ja/testing.html
https://readouble.com/laravel/7.x/ja/dusk.html

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

PHPStormからDockerのPHPコンテナでPHPUnitを実行する方法

はじめに

ローカル環境でDockerを利用しているときに、
PHPStormの画面上からPHPUnitを実行できるようにするための
設定方法を紹介します。

大きく2つの設定が必要になります。

  • PHP interpreterを設定
  • PHPUnitのinterpreterを設定

PHP interpreterを設定

・「Settings」->「Languages & Frameworks」->「PHP」->「CLI Intepreter」->「...」をクリック
1.PNG

・左上の「+」->「From Docker, Vagrant, VM, WSL, Remote...]をクリック
2.PNG

・「Docker Compose」のラジオボタンを選択する
→「Configuration file」にdocker-compose.ymlのパスを設定
→「Service」でphp-fpmのコンテナを選択
→「OK」クリック
※「Docker」を選択すると、PHPUnitでDBコンテナを利用する際に接続できないので「Docker Compose」で設定する
2.PNG

PHPUnitのinterpreterを設定

・「Settings」->「Languages & Frameworks」->「PHP」->「Test Frameworks」->左上の「+」->「PHPUnit by Remote Interpreter」をクリック
4.PNG

・先ほど登録したDockerコンテナのInterpreterを選択
3.PNG

・「Path to script」にDockerコンテナのautoload.phpのパスを設定
4.PNG

・「Default configuration file」にphpunit.xmlのパスを設定
5.PNG

・PHPStomのテストクラスファイルを開いて、左にある緑の三角マークをクリックでテスト実行
9.PNG

・テスト結果確認
PHPStormの左下の「Run」タブが表示され、そこにテスト結果が表示されます。
キャプチャ.PNG

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

laravel web.phpで解決 データベース項目追加できなかった件

課題で入力フォームを増やすというものがあったが、どれだけフォームを変更してもデータベースが更新されず常におなじ値になっていた。

原因は、以下の// Eloquent モデルが定数になっていたこと

use App\Book;
use Illuminate\Http\Request;

/**
* 本のダッシュボード表示(books.blade.php)
*/
Route::get('/', function () {
    $books = Book::orderBy('created_at', 'asc')->get();
    return view('books', [
        'books' => $books
    ]);
    //return view('books',compact('books')); //も同じ意味
});

/**
* 新「本」を追加 
*/
Route::post('/books', function (Request $request) {

    //バリデーション
    $validator = Validator::make($request->all(), [
        'item_name' => 'required|max:255',
        'item_number' => 'required|min:1|max:3',
        'item_amount' => 'required|max:6',
        'published' => 'required|min:7',
    ]);

    //バリデーション:エラー 
    if ($validator->fails()) {
        return redirect('/')
            ->withInput()
            ->withErrors($validator);
    }
    //以下に登録処理を記述(Eloquentモデル)
// Eloquent モデル
    $books = new Book;
    $books->item_name = $request->item_name;
    $books->item_number = $request->item_number;
    $books->item_amount = $request->item_amount;
    $books->published = $request->published;
    $books->save(); 
    return redirect('/');




});

/**
* 本を削除 
*/
Route::delete('/book/{book}', function (Book $book) {
    $book->delete();       //追加
    return redirect('/');  //追加

});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む