20200708のlaravelに関する記事は10件です。

【Laravel】PHPテンプレートの利用

書籍のアウトプットとして

ビューについて

本格的なWEBページをHTMLを使って表示内容を記述できる仕組みが必要。
このために用意されているのが「テンプレート」
テンプレートはLaravelのビュー(View)を担当している。
MVCのに基づいたビューは画面表示関連をわかりやすい形で作れるように成なる。

アドレスにアクセスし、コントローラはテンプレートを読み込んで表示するが、ただ単にHTMLコードを表示しているわけではない。

レンダリングの考え方

レンダリングとはLaravelがテンプレートを読み込んで情報をはめ込む作業のこと。

Laravelでは以下の2つのテンプレートが用意されている。

手法 説明
PHPのソースコードをそのまま使用する方法
Blade Laravel独自

PHPテンプレートを作る

ここからは実際にテンプレートを作ってみる。

テンプレートの作成

以下の手順で作成。
1. テンプレートファイルをresourcesフォルダ内のviews度言うフォルダの中に作成
2. helloフォルダを作成
3. helloフォルダにindex.phpを作成

index.php
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Hello/Index</title>
    <style>
    </style>
  </head>
  <body>
    <h1>Index</h1>
    <p>this is a sample page with php-template.</p>
  </body>
</html>

2に関して、テンプレートは各コントローラごとにフォルダを用意し、その中にコントローラで使うテンプレートをまとめておくのが一般。

ルートの設定でテンプレートを表示

web.phpに追記

web.php
Route::get('hello', function () {
    return view('hello.index');
});

その後/helloにアクセスすると画面が表示される。

viewメソッドについて

web.phpでは第2引数のクロージャでviewというメソッドを使用している。
viewは引数にテンプレート名を指定すると、そのテンプレートを読み込んで返す。

view('フォルダ名.ファイル名')

ここで単にview('hello')とすると、viewsフォルダからhelloろ言うファイルを探してしまう。

ここでviewは「テンプレートを読み込んでその内容を返す」というわけはない
viewが返すのはテンプレートのレンダリング結果がコンテンツとして設定されているResponseインスタンス。
結果として「テンプレートを読み込んでその内容を返す」用に見えるだけで実際はそのような動きではないことに注意。

コントローラでテンプレートを使う

先のルート情報のクロージャで使ったviewをそのままアクションメソッド内で利用するだけ。

HelloControllweクラスのIndexメソッドを修正

    public function index()
    {
      return view('hello.index');
    }

ルート情報を修正

web.php
Route::get('hello', 'HelloController@index');

/helloにアクセスると同じ結果になる。
Route::getでviewするか
Route::getで呼び出されたアクションメソッドでviewするかの違い

値をテンプレートに渡す

index.phpを修正

index.php
  <body>
    <h1>Index</h1>
    <p><?= $msg;?></p>
    <p><?= date("Y年n月j日");?></p>
  </body>

index.phpテンプレートはPHPスクリプトであるため、PHPが記述できる。
$msgに値を渡すためにHelloControllerクラスを修正

    public function index()
    {
      $data=['msg'=>'これはコントローラから渡されたメッセージ'];
      return view('hello.index',$data);
    }

/helloにアクセスすると値が渡されていることがわかる。

テンプレへの値の受け渡し

先の例ではindexメソッドのviewメソッドを呼び出している。
viewの呼び出しは以下のようにする。

return view(テンプレ,配列)

第2引数には**配列(連想配列)**が渡されている。

今回は['msg'=>'これはコントローラから渡されたメッセージ']を渡した。
これは配列の値(これはコントローラから渡されたメッセージ)がキー(msg)という名前の変数としてテンプレで用意される。
このようにviewの第2引数では配列を渡すと、キーが変数名、値がその変数の値となって渡される。

ルートパラメ-タをテンプレに渡す

アクセス時にアドレスに記載した値がそのままテンプレへ表示させるにはどうするか。

これには2つの切り分けをする
- ルートパラメータを受け取る部分
- 値をテンプレに書き出す部分

ルートパラメータを受けるにはアクション引数に仮引数を用意し、Route::getでアドレスにパラメータを追記すればいいのだった。
あとはこれをテンプレに渡して表示するだけ。
実際にやってみる。

index.php
<body>
    <h1>Index</h1>
    <p><?=$msg;?></p>
    <p>ID=<?=$id;?></p>

indexメソッドを書き換える

    public function index($id='zero')
    {
      $data=[
        'msg'=>'これはコントローラから渡されたメッセージ',
        'id'=>$id
      ];
      return view('hello.index',$data);
    }
web.php
Route::get('hello/{id?}', 'HelloController@index');

これで/hello/userとアクセスすると、ルートパラメータの値が表示されていることが確認できる。

クエリ文字列の利用

アクセスするアドレスの情報を利用して値を渡す方法のもう一つの方法として、「クエリ文字列」を用いる事ができる。

クエリ文字列はルートパラメ-とは受け取り方が違う。

indexメソッドを書き換える。

    public function index(Request $request)
    {
      $data=[
        'msg'=>'これはコントローラから渡されたメッセージ',
        'id'=>$request->id
      ];
      return view('hello.index',$data);
    }

ここであRequestインスタンスを渡している。渡す値は$request->$idのようにして引き渡している。

web.php
Route::get('hello', 'HelloController@index');

web.phpはこのように書き換えるが{$id?}が消えている。
ごく一般的なルート情報の記述に戻っている。
そして以下のようにアクセスすると正しく受け取れている。
/hello/?id=sample
ここで?id=sampleのようにしてidというキーにsampleという値をわつぃている。

このようにクエリ文字列を使って渡された値は$request->キー名で取り出せる。
キー名とは/hello/?○=sampleのところ

Bladeテンプレ

laravelは独自のBladeテンプレがある。この記述法を書いていく。

Bladeを使う

PHPスクリプトをそのまま使うのは以下のデメリットが有る

  • ちょっと書くだけでいいのに<?php print ○○;?>と書かなければならない
  • PHPは<>で表示されHTMLを同じ形式で書くがこれが、HTML作成ツールなどで構造が崩れてしまう事がある。
  • ページを分割してレイアウトする機能がない
  • すべてHTMLとPHPで手作業でレイアウトするしかない

Bladeはいくつかの機能を持っている。

  • テンプレを継承して新たなテンプレを作る。
  • レイアウトの一部をセクションとしてはめ込むことでレイアウトが作れる。

テンプレを作る

Bladeのテンプレもresourcesのviewsフォルダの中に作成する。
Bladeテンプレファイルは〇〇.blade.phpという名前にする。
ここではindex.blade.phpという名前で作成する。
では記述していく

index.blade.php
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Hello/Index</title>
    <style>
    body{font-size:16pt;color:#999;}
    h1{
      font-size: 50pt;text-align: right;color:#f6f6f6;margin:-20px 0px -30px 0px;letter-spacing: -4pt;
    }
    </style>
  </head>
  <body>
    <h1>Blade/Index</h1>
    <p>{{$msg}}</p>
  </body>
</html>

ポイントは{{$msg}}と書いているところ。
Bladeでは{{変数}}のようにしてテンプレに埋め込む。

アクションの修正

次にコントローラのアクションメソッドを修正していく

    public function index()
    {
      $data=[
        'msg'=>'これはコントローラから渡されたメッセージ'
      ];
      return view('hello.index',$data);
    }

アクションメソッドは変わらない。
web.phpはこのように。

web.php
Route::get('hello', 'HelloController@index');

/helloにアクセスすると正しく表示できている。

index.phpindex.blade.php

今回アクションメソッドでview('hello.index',...としているのindex.blade.phpのほうが実行されている。
LaravelではBladeテンプレがあるとそれが優先して読み込まれる。

フォームを利用する

フォームを利用してみる
以下のように修正する。

index.blade.php
  <body>
    <h1>Blade/Index</h1>
    <p>{{$msg}}</p>
    <form action="/hello" method="post">
      @csrf
      <input type="text" name="msg">
      <input type="submit">
    </form>
  </body>

ポイントはこれ

@csrf

Bladeディレクティブといい、テンプレに決まったコードを生成して書き出す。

CSRF対策について

@csrfはCSRF対策のためのBladeディレクティブ。
CSRFはスクリプトなどから外部からフォームを送信するもので、フォームに大量のコンテンツを送りつけりする。
@csrfトークンというランダムな非表示フィールドとして追加する。
このトークン値が正しいフォームだけを受け入れるようにする。
こうすることで正しいフォームからの送信かどうかを見分けることができる。

LaravelではCSRF対策がなされていないフォームの送信は例外が発生して受付けられないようになっている。
そのため、フォームを利用するときは必ず@csrfをフォームに用意しておく必要がある。

アクションの用意

コントローラアクションを用意する。
ここでは2つの処理を書いていく

  • /helloへアクセスしたとき
  • フォームを送信したとき

以下のように修正する。

    public function index()
    {
        $data=[
        'msg'=>'名前を入力'
      ];
        return view('hello.index', $data);
    }
    public function post(Request $request)
    {
        $msg=$request->msg;
        $data=[
        'msg'=>'あなたは'.$msg.'です。'
      ];
        return view('hello.index', $data);
    }

indexメソッドは/helloにアクセスしたときの処理。
postメソッドはフォームを送信したときの処理
ここでRequestインスタンスを引数に渡してフォームの内容を取得している。

$msg=$request->msg;

フォームのところにname="msg"と指定したのは
$msg=$request->msg;で取得するため。

フォームで送信された値はすべてnameプロパティとして取り出せる。

POSTのルート設定

ルート情報を追記する

web.php
Route::post('hello', 'HelloController@post');

POST送信はRoute::postを設定する。使い方はROoute::getと同じ。

同じアドレスでもPOST,GETのようにアクセスするメソッドが違えば両方ともに使える。

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

【Laravel】Bladeでレイアウトを作成する

はじめに

LaravelのBladeテンプレートで使えるレイアウトの「継承」を利用し、複数の「セクション」を組み合わせてレイアウトを作成する機能をまとめます。

図説

コメント 2020-07-08 181953.png

extend

最初に記載すべき項目としてレイアウトの継承設定があります。

@extends('layouts.*')

部品側のファイルに記載することで、土台側(親)のファイルを読み込んでレイアウトを継承します。
これを書かないとそもページ自体を作ることができないので必須です。

sectionとyield

section

@section('content')
@endsection

@sectionはページで表示するコンテンツの区画を定義する事ができ、同じ名前のyieldにはめ込まれます。

yield

@yield('content')

@yieldはコンテンツの配置場場所を定義するもので、同じ名前のsectionが部品側のファイルにある場合コンテンツの内容が表示されます。

titleの様に変数名を渡す場合は@endsectionのような閉じタグを用意する必要がなく@sectionタグだけでコンテンツを定義する事ができます。

parent

@section('sidebar')
  @parent
@endsection

sectionに対応する配置場所の定義はyieldが行いますが、今回「sidebar」にはyieldではなくsectionが用いられています。この場合ははめ込みではなく既にsection内にあった内容を上書きする形になります。
そうすると親のsectionにもともとあった内容が消えてしまうので、親のsection内容を残して表示させたい時は、子のsectionの中に「@parent」ディレクティブを用意してあげる事で、親のsection内容がそこに表示されるようになります。

include

@include('名前')

@includeはsectionのようにコンテンツとしてではなく、より単純にテンプレートをただはめ込んで表示させたい場合に使用します。なのでサブビューのファイルではコンテンツをsectionで囲う必要がありません。
includeでもって来たビューの内容を「サブビュー」といいます。

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

Laravel 6で認証機能を入れる

開発環境構築

以下の環境を構築した上で、そのプロジェクトで実行しています。
https://qiita.com/ryuseino/items/e0e3a77245635b7cc101

usersテーブル作成

とりあえずLaravelにデフォルトでついてくるMigrationを使ったusersテーブルでやります。
なのでまずはテーブル作成のコマンド実行。

php artisan migrate

Composerパッケージインストール

以下のコマンドを実行することで認証が簡単に出来るようになります。

composer require laravel/ui "^1.0" --dev
php artisan ui vue --auth
npm install && npm run dev

localhostを開く

開発環境構築後の確認と同じく、localhostを開いてみるとLOGINとREGISTERというリンクが上部に出ています。
スクリーンショット 2020-07-08 17.07.43.png

それぞれ極々普通のログインと会員登録の機能になっています。
そんな訳で簡単に認証が作れることが分かりました。
この段階ではまだemailのverifyなどがないので、それらは後で追加する必要がありそうです。

参考になりそうなページ

https://readouble.com/laravel/6.x/ja/authentication.html

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

Laravel、web.phpのルーティングとコントローラーのつながりがよくわからない

LaravelのRoutesとView、Controllerのつながりについての質問

問題点、質問:htmlからリンクで指定したルーティングにデバックが通らない。(<aタグ>GETメソッド)

Route::resourceは問題なく処理が通るのですが、追加で記述した
Route::get('/book/csvDownload','BookController@csvDownload')->name('book.csvDownload');
がうまく通りません。

デバッグで試してみるとRoute::resourceはコントローラー側に処理が通っているのに対し、追記したものはコントローラー側に処理が来ていません。

html(php)でリンク(<a>タグ)先にアクセスするとき、ルーティングの設定(web.php)を基にコントローラーへ割り振っているという認識です。
また、開発環境にはeclipse(php,xampp)、webサーバにはapacheサーバを使っています。

ルーティングの設定ファイル(web.php)

web.php
use Illuminate\Support\Facades\Route;

//RouteResourceメソッドを使用することで、Restfulなルーティングを行うことができる
Route::resource('book','BookController');
/*この場合、以下のようにルーティングされます。
 * GET   |   /book           |   BookController@index    |一覧画面表示
 * GET   |   /book/{book}    |   BookController@show     |詳細画面表示
 * GET   |   /book/create    |   BookController@create   |登録画面表示
 * POST  |   /book           |   BookController@store    |登録処理
 * GET   |  /book/{book}/edit|   BookController@edit     |編集画面表示
 * PUT   |   /book/{book}    |   BookController@update   |編集処理
 * DELETE|  /book/{book}     |   BookController@destroy  |削除処理
 */
//問題のルーティング箇所
//このURLにアクセスされたときにcsvファイルに情報を出力する処理に飛ばす
Route::get('/book/csvDownload','BookController@csvDownload')->name('book.csvDownload');

コントローラーファイル

BookController.php
namespace App\Http\Controllers;
use App\Book;
use Illuminate\Http\Request;

/**
**
**前略
**
*/
 public function destroy($id){
        $book=Book::findOrFail($id);
        $book->delete();

        return redirect("/book");
    }

    public function create(){
        $book=new Book();
        return view('book/edit',compact('book'));
    }

    public function store(Request $request){
        $book = new Book();
        $book->name = $request->name;
        $book->price = $request->price;
        $book->author = $request->author;
        $book->save();

        return redirect("/book");
    }
//問題のメソッド
    public function csvDownload(){
        //データベースからすべてのデータを抽出
        $books=Book::all();

        //指定されたディレクトリ空のcsvファイルを生成
        $res = touch("C:\Users\y_takeuchi\Downloads\books.csv");

        if($res==false){
            rmdir("C:\Users\y_takeuchi\Downloads\books.csv");
            return redirect("/book");
        }

        //指定したパスのファイルを書き込みで開く
        $file = fopen('C:\Users\y_takeuchi\Downloads\books.csv','w');

        //csv作成
        fputcsv($file,['name','price','author']);
        foreach($books as $entity){
            fputcsv($file, [$entity->name,$entity->price,$entity->author]);
        }
        fclose($file);

        return redirect("/book");

View

index(.blade).php
<!DOCTYPE html>
<html>
<head>
<title>Laravel Sample</title>
<link rel="stylesheet"  href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container ops-main">
    <div class="row">
        <div class="col-md-12">
            <h3 class="ops-title">書籍一覧</h3>
        </div>
    </div>
    <div class="row">
        <div class="col-md-11 col-md-offset-1">
            <table class="table text-center">
                <tr class="text-center">
                    <th>ID</th>
                    <th>書籍名</th>
                    <th>価格</th>
                    <th>著者</th>
                    <th>削除</th>
                </tr>
                @foreach($books as $book)
                <tr>
                    <td><a href="/sample/book/{{$book->id}}/edit">{{$book->id}}</a></td>
                    <td>{{$book->name}}</td>
                    <td>{{$book->price}}</td>
                    <td>{{$book->author}}</td>
                    <td>
                        <form action="/sample/book/{{$book->id}}" method="post">
                            <input type="hidden" name="_method" value="DELETE">
                            <input type="hidden" name="_token" value="{{csrf_token()}}">
                            <button type="submit" class="btn btn-xs btn-danger" aria-label="Left Align">
                                <span class="glyphicon glyphicon-trash"></span>
                            </button>
                        </form>
                    </td>
                </tr>
                @endforeach
            </table>

<!--問題の箇所
            <div><a href="/sample/book/create" class="btn btn-default">新規作成</a></div>
            <div><a href="/sample/book/csvDownload" class="btn btn-default">csvダウンロード</a></div>
-->     
            </div>
    </div>
</div>
</body>
</html>
<!-- Laravelではビューの作成にBladeというテンプレートを使っています。 -->

試みたこと:

・キャッシュが残っているという情報があったので、php artisan route:listでクリーンしました。

・Route::resourceがあると、ほかのルーティングが通らないのかと思い、Route::resourceを
Route::get('/book','BookController@index');
Route::get('/book/{book}','BookController@show');
Route::get('/book/create','BookController@create');
Route::post('/book','BookController@store');
Route::get('/book/{book}/edit','BookController@edit');
Route::put('/book/{book}','BookController@update');
Route::delete('/book/{book}','BookController@destroy');

と書き直しました。すると、つぎは、Route::get('/book/create','BookController@create');も処理が通らなくなってしまいます。

・テンプレート側を<a>タグではなく<form>タグで送信しましたが、結果は同じく表示されませんでした。

・NotFound404にはならず、画面が遷移せずにその場にとどまったままURLだけ変わっています。

ご教授いただけるとありがたいです。

参考サイト引用:https://qiita.com/sano1202/items/6021856b70e4f8d3dc3d

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

Amazon EC2 LinuxでLaravelのphp artisan db:seedが上手くいかない時

【エラーメッセージ】

[ec2-user@ip-172-31-11-201 sample]$ php artisan db:seed

In DatabaseSeeder.php line 14:

  Parse error: syntax error, unexpected end of file

【開発環境】

Amazon EC2 Linux
Windows 10 HOME
Apache/2.4.43
Laravel Framework 5.4.36
vsftpd: Ver 3.0.2

Tera Term 4.1.105
FFFTP Ver 4.7

【対応】

ローカルで同じファイルで実行出来たのでAWSに上げる過程で何をやったか?と考えてみると、、

FTPか?

まさかと思って文字コードの設定を見てみると

SJIS になっていた。。
(FFFTPでは初期設定してもローカル側の文字コードが勝手に変わる現象を思い出した。)

これをUTF8に直して再び 「php artisan db:seed」を実行すると

[ec2-user@ip-172-31-11-201 sample]$ php artisan db:seed
Seeding: BooksTableSeeder

と成功しテーブルへの設定も問題なし。

1.jpg

【参考】

Laravel入門 - 使い方チュートリアル

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

LaravelでLINE BOT(オウム返し)を実装する。

Laravel 5.5

LINE BOTのオウム返しをlaravelで実装してみる。

line-bot-sdk-phpをインストールする。

composer require linecorp/line-bot-sdk

route/api.phpにwebhookURLを設定する。

注意:route/web.phpに設定してしまう事があるので間違えないようにする。

route/api.php
Route::group(['namespace' => 'Api'], function() {
    // LineからのWebhookを受信
    Route::post('/line/webhook', 'LineController@webhook')->name('line.webhook');
});

LINE Developersで設定したチャンネルから
チャンネルアクセストークン、チャンネルシークレットを確認し
.envに設定する

LINE_ACCESS_TOKEN=*********チャネルアクセストークン**********
LINE_CHANNEL_SECRET=*********チャネルシークレット**********
Api/LineController.php
<?php

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use LINE\LINEBot;
use LINE\LINEBot\Constant\HTTPHeader;
use LINE\LINEBot\SignatureValidator;
use LINE\LINEBot\HTTPClient\CurlHTTPClient;
use LINE\LINEBot\MessageBuilder\TextMessageBuilder;
use Exception;

class LineController extends Controller
{
    public function webhook (Request $request)
    {
        $lineAccessToken = env('LINE_ACCESS_TOKEN', "");
        $lineChannelSecret = env('LINE_CHANNEL_SECRET', "");

        // 署名のチェック
        $signature = $request->headers->get(HTTPHeader::LINE_SIGNATURE);

        if (!SignatureValidator::validateSignature($request->getContent(), $lineChannelSecret, $signature)) {
            // TODO 不正アクセス
            return;
        }

        $httpClient = new CurlHTTPClient ($lineAccessToken);
        $lineBot = new LINEBot($httpClient, ['channelSecret' => $lineChannelSecret]);

        try {
            // イベント取得
            $events = $lineBot->parseEventRequest($request->getContent(), $signature);

            foreach ($events as $event) {
                file_put_contents($file, $event . PHP_EOL, FILE_APPEND);
                // 入力した文字取得
                $message = $event->getText();
                $replyToken = $event->getReplyToken();
                $textMessage = new TextMessageBuilder($message);
                $lineBot->replyMessage($replyToken, $textMessage);
            }
        } catch (Exception $e) {
            // TODO 例外
            return;
        }
        return;
    }
}

※変数の中身の見方(logファイルの設定)
LINEBotは、変数をddなどで確認できないので
ログファイルに変数などを書き込み正しくデータが取れているか確認する。
これ以外の方法もあるので各自調べてください。

file_put_contents(__DIR__ . "/log.txt", $request->getContent() . PHP_EOL, FILE_APPEND);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

新規プロジェクトの作成時にGitでやっておくべきこと

プロジェクトを新規作成する際に最初にやるべきことは、Gitコマンドによる開発環境の構築になります。
本記事では、新規プロジェクト作成からgit-flowモデルでの開発環境の構築手順をまとめました。
なお、Composerは既にインストール済みのものとしています。

環境

MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)
PHP 7.4.1
Laravel Framework 7.18.0

Laravelプロジェクト作成

composer create-project --prefer-dist laravel/laravel SampleProject

localhost起動確認

  cd SampleProject
  php artisan serve
  Laravel development server started: <http://127.0.0.1:8000>

ステージング領域作成からプッシュまで

git init
Initialized empty Git repository in 作業ディレクトリのパス
git add .
git commit -m "コミットメッセージ"
git remote add origin リモートリポジトリURL
git push -u origin HEAD

作業ブランチを新規作成

git checkout -b develop
git checkout -b feature/作業ブランチ名
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravelで新規プロジェクトを作成する時にGitでやっておくべきこと

プロジェクトを新規作成する際に最初にやるべきことは、Gitコマンドによる開発環境の構築になります。
本記事では、新規プロジェクト作成からgit-flowモデルでの開発環境の構築手順をまとめました。
なお、Composerは既にインストール済みのものとしています。

環境

MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)
PHP 7.4.1
Laravel Framework 7.18.0

Laravelプロジェクト作成

composer create-project --prefer-dist laravel/laravel SampleProject

localhost起動確認

  cd SampleProject
  php artisan serve
  Laravel development server started: <http://127.0.0.1:8000>

ステージング領域作成からプッシュまで

git init
Initialized empty Git repository in 作業ディレクトリのパス
git add .
git commit -m "コミットメッセージ"
git remote add origin リモートリポジトリURL
git push -u origin HEAD

作業ブランチを新規作成

git checkout -b develop
git checkout -b feature/作業ブランチ名
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel Eloquantでデータを得ようとしたらエラーが出た話

目的

  • idカラムの値を指定してレコードのデータを取得しようとした際にエラーが発生した話をまとめる

実施環境

  • ハードウェア環境
項目 情報
OS macOS Catalina(10.15.5)
ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports)
プロセッサ 2 GHz クアッドコアIntel Core i5
メモリ 32 GB 3733 MHz LPDDR4
グラフィックス Intel Iris Plus Graphics 1536 MB
  • ソフトウェア環境
項目 情報 備考
PHP バージョン 7.4.3 Homwbrewを用いて導入
Laravel バージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う
MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする

問題までの経緯

  1. モデルファイルをアプリ名ディレクトリ/app直下からアプリ名ディレクトリ/app/Models直下に移動した。(Modelsディレクトリはmkdirコマンドにて作成した。)

  2. Laravelアプリ名ディレクトリで下記コマンドを実行してtinkerを開いた。

    $ php artisan tinker
    
  3. 下記を実行してuse宣言を行った。

    use App\Models\モデルファイル名
    
  4. 下記を実行してidカラムが1のレコードのデータを取得しようとした。

    $info = モデル名::find(1)
    

問題

  1. 下記のエラーが発生した。
PHP Fatal error:  Cannot declare class App\モデルファイル名, because the name is already in use in /usr/share/nginx/html/Laravelアプリ名/app/Models/モデルファイル名.php on line 7
PHP Stack trace:
PHP   1. {main}() /usr/share/nginx/html/Laravelアプリ名/artisan:0
PHP   2. App\Console\Kernel->handle() /usr/share/nginx/html/Laravelアプリ名/artisan:37
PHP   3. Illuminate\Console\Application->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:131
PHP   4. Illuminate\Console\Application->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Console/Application.php:93
PHP   5. Illuminate\Console\Application->doRun() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:147
PHP   6. Illuminate\Console\Application->doRunCommand() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:271
PHP   7. Laravel\Tinker\Console\TinkerCommand->run() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:1000
PHP   8. Laravel\Tinker\Console\TinkerCommand->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Console/Command.php:121
PHP   9. Laravel\Tinker\Console\TinkerCommand->execute() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Command/Command.php:255
PHP  10. Illuminate\Foundation\Application->call() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Console/Command.php:134
PHP  11. Illuminate\Container\BoundMethod::call() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/Container.php:590
PHP  12. Illuminate\Container\BoundMethod::callBoundMethod() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:34
PHP  13. Illuminate\Container\Util::unwrapIfClosure() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:90
PHP  14. Illuminate\Container\BoundMethod::Illuminate\Container\{closure:/usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:30-34}() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/Util.php:37
PHP  15. call_user_func_array:{/usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32}() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
PHP  16. Laravel\Tinker\Console\TinkerCommand->handle() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32
PHP  17. Psy\Shell->run() /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/tinker/src/Console/TinkerCommand.php:78
PHP  18. Psy\Shell->run() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:316
PHP  19. Psy\Shell->doRun() /usr/share/nginx/html/Laravelアプリ名/vendor/symfony/console/Application.php:147
PHP  20. Psy\Shell->doInteractiveRun() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:341
PHP  21. Psy\ExecutionLoopClosure->execute() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:370
PHP  22. Psy\{closure:/usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/ExecutionLoopClosure.php:32-100}() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/ExecutionClosure.php:96
PHP  23. Psy\Shell->getInput() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/ExecutionLoopClosure.php:40
PHP  24. Psy\Shell->addCode() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:521
PHP  25. Psy\CodeCleaner->clean() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/Shell.php:829
PHP  26. PhpParser\NodeTraverser->traverse() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner.php:227
PHP  27. PhpParser\NodeTraverser->traverseArray() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:91
PHP  28. PhpParser\NodeTraverser->traverseNode() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:223
PHP  29. PhpParser\NodeTraverser->traverseNode() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:146
PHP  30. Psy\CodeCleaner\ValidClassNamePass->leaveNode() /usr/share/nginx/html/Laravelアプリ名/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php:153
PHP  31. Psy\CodeCleaner\ValidClassNamePass->validateStaticCallExpression() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:93
PHP  32. Psy\CodeCleaner\ValidClassNamePass->ensureMethodExists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:180
PHP  33. Psy\CodeCleaner\ValidClassNamePass->ensureClassOrTraitExists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:271
PHP  34. Psy\CodeCleaner\ValidClassNamePass->traitExists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:255
PHP  35. trait_exists() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:375
PHP  36. spl_autoload_call() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:375
PHP  37. Composer\Autoload\ClassLoader->loadClass() /usr/share/nginx/html/Laravelアプリ名/vendor/psy/psysh/src/CodeCleaner/ValidClassNamePass.php:375
PHP  38. Composer\Autoload\includeFile() /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:322
PHP  39. include() /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:444

   Symfony\Component\Debug\Exception\FatalErrorException  : Cannot declare class App\モデルファイル名, because the name is already in use

  at /usr/share/nginx/html/Laravelアプリ名/app/Models/モデルファイル名.php:7
     3| namespace App;
     4| 
     5| use Illuminate\Database\Eloquent\Model;
     6| 
  >  7| class モデルファイル名 extends Model
     8| {
     9|     //
    10| }
    11| 

  Exception trace:

  1   Symfony\Component\Debug\Exception\FatalErrorException::__construct()
      /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:148

  2   Illuminate\Foundation\Bootstrap\HandleExceptions::fatalExceptionFromError()
      /usr/share/nginx/html/Laravelアプリ名/vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap/HandleExceptions.php:134

  Please use the argument -v to see more details.

   Whoops\Exception\ErrorException  : Cannot declare class App\モデルファイル名, because the name is already in use

  at /usr/share/nginx/html/Laravelアプリ名/app/Models/モデルファイル名.php:7
     3| namespace App;
     4| 
     5| use Illuminate\Database\Eloquent\Model;
     6| 
  >  7| class モデルファイル名 extends Model
     8| {
     9|     //
    10| }
    11| 

  Exception trace:

  1   ()
      /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:444

  2   Composer\Autoload\includeFile()
      /usr/share/nginx/html/Laravelアプリ名/vendor/composer/ClassLoader.php:322

  Please use the argument -v to see more details.

問題解決までの経緯

  1. データの取得に使用するモデルファイルを確認した。下記にモデルファイルの内容を記載する。

    アプリ名ディレクトリ/app/Models/モデルファイル.php
    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class モデルファイル名 extends Model
    {
        //
    }
    
  2. モデルファイルの設置場所を変更したにもかかわらずモデルファイル内のnamespaceの記載を変更していなかった。

  3. 下記の様にモデルファイルを修正した。

    アプリ名ディレクトリ/app/Models/モデルファイル.php
    <?php
    
    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Model;
    
    class モデルファイル名 extends Model
    {
        //
    }
    
  4. 下記の手順を実施して正常にidが1のレコードのデータを取得できたことが確認できた。

    1. Laravelアプリ名ディレクトリで下記コマンドを実行してtinkerを開く。

      $ php artisan tinker
      
    2. 下記を実行してuse宣言を行う。

      use App\Models\モデルファイル名
      
    3. 下記を実行してidカラムが1のレコードのデータを取得した。

      $info = モデル名::find(1)
      
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel $loop変数のプロパティと実行結果

foeachの$loop変数のプロパティ

$loop ループ変数 プロパティ
index インデックス番号
iteration 繰り返し数(1スタート)
remaining 残っている要素数
count 配列の総数
first 最初の項目か
last 最後の項目か
even 偶数回目か
odd 奇数回目か
depth 入れ子レベル
parent 親のループ変数(ネストの入れ子の場合)

サンプル

Controller

ViewController.php
public function foreach_loop()
{
  return view('view.foreach_loop', [
     'weeks' => ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
  ]);
}

bladeテンプレート

foreach_loop.blade.php
<table class="table">
<tr>
  <th>value</th>
  <th>index</th>
  <th>iteration</th>
  <th>count</th>
  <th>first</th>
  <th>last</th>
  <th>even</th>
  <th>odd</th>
  <th>depth</th>
</tr>
@foreach($weeks as $week)
<tr>
  <td>{{ $week }}</td>
  <td>{{ $loop->index }}</td>
  <td>{{ $loop->iteration }}</td>
  <td>{{ $loop->count }}</td>
  <td>{{ $loop->first }}</td>
  <td>{{ $loop->last }}</td>
  <td>{{ $loop->even }}</td>
  <td>{{ $loop->odd }}</td>
  <td>{{ $loop->depth }}</td>
</tr>
@endforeach
</table>

実行結果

Screen Shot 0032-07-08 at 5.37.34.png

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