4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】非同期処理をJavaScriptのFetch APIで実装する

Last updated at Posted at 2023-01-01

Fetch APIによる非同期処理とは?

Fetch APIはブラウザに搭載された非同期処理をするための関数です。
fetch関数を用いることで、ブラウザのページを全て更新することなく
一部分だけを更新する非同期処理が実行できます

非同期処理のFetch関数の使い方

LaravelではModel View Controllerの3つに分けてコードを管理するため
fetchメソッドもMVCの流れに沿う必要があります

fetch関数は第一引数に指定したURLにhttp通信(リクエスト)を送信することで
Laravelのルーティングを経由しコントローラに記述したアクションを実行します

コントローラ側でデータベースの操作および情報を取得した処理を実行した後、
fetch関数に対して実行結果(レスポンス)を返します。

JavaScriptにはブラウザのHTMLを書き換えたり追記したりする機能があるため
必要に応じて現在表示されているブラウザのHTMLにレスポンスの内容を反映させます
つまり非同期で部分的にHTMLを書き換えることができます

対応するブラウザは?

ブラウザ バージョン
IE 非対応
Edge 14〜
Firefox 39〜
Chrome 42〜
Safari 10.1〜

同じ非同期処理のajaxとの違いは?

  • 非同期処理を実装する方法は複数存在し、fetchの他に挙げられるのが
    ajaxという方法になります。

  • ajaxを実行するためにはまず、jQueryのライブラリを読み込む必要があります。
    fetchはブラウザが既にライブラリを搭載しているため
    ライブラリを読み込む必要がありません

  • fetchは最新のブラウザであれば機能しますが、古いブラウザの場合
    機能しない場合があります。
    jQueryでも一概には言えませんが、ajaxではブラウザの違いによる誤作動を
    ある程度許容することができます

元となるHTMLコード

index.braid.html

<table class="table">
    <tr id="result">
        <th>id</th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
</table>

LaravelでFetchを動かすための基本知識

JavaScriptをhtmlに直接記述する場合

index.braid.html

<table class="table">
    <tr id="result">
        <th>id</th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
</table>

<script type="text/javascript">

// ここに処理を記述します 

</script>

JavaScriptを呼び出す場合

  • ファイルの保存場所はLaravelのプロジェクト内部に存在する次のフォルダに保存します

  • public¥js¥fetch.js

  • 呼び出す際のパスはjs/fetch.jsで呼び出せます

index.braid.html

<table class="table">
    <tr id="result">
        <th>id</th>
        <th>商品名</th>
        <th>価格</th>
    </tr>
</table>

<script src="js/fetch.js"></script>

データベースのテーブル情報を一覧表示する

  • 非同期通信処理つまりfetchのコードはJavaScriptファイルに記述します
  • javascriptのscriptタグはbodyタグの最後に書くことが推奨されます。
  • javascriptの書き方は外部ファイルとして呼び出す場合と
    scriptタグに直接記述する方法があります

JavaScriptにfetch(非同期処理)を記述する

  • テーブルの一覧を表示する処理を実行する関数を作成します
  • 関数の名前は任意で命名しますが命名規則で先頭小文字のキャメルケースです。
  • 各構成語の先頭を大文字にする方式で記述します
  • 例:indexAll
fetch.js
function indexAll(){
    // ここにfetch関数のコードを記述していきます
}

// 最後に関数を実行します

// functionを動かす条件として”ボタンを押した場合”などの条件がない場合は
// ブラウザが更新されるとコードが上から順に、つまりHTMLとjavascriptが読み込まれるため
// indexAllは自動で実行されることになります

indexAll();

fetchの基本構文

通常の書き方

  • fetchメソッドは通信が成功したか、失敗したかを結果として返します
  • 結果を参照する場合はfetchメソッドのpromiseオブジェクトを呼び出します
  • phpから受け取ったpromiseオブジェクトをJavaScriptで利用するためにはJSONファイルに変換が必要です
  • 後述のメソッドチェーンを利用するとfetchから取得した結果をそのまま別のメソッドに渡すことができます。
fetch.js

function indexAll(){

        
        fetch('URLを記述する第一引数') //(1)
        .then((任意の変数名1) => {return 任意の変数名1.json()}) //(2)
        .then((任意の変数名2) => { //(3)
                    
                                //(4) 

                                }) 
        
        .catch(error => {
                                //(5)
                            alert("実行失敗"); 
                            alert(error);
                        })
                    }

//(1) コントローラーへ繋がるURLを記述することで
//(1) コントローラーへ「データベースの情報が欲しい」と"リクエスト"を送信します
//(1) コントローラーのアクションには「データベースの情報を操作する処理」を記述しておき
//(1) アクションを実行することでデータベースのテーブル情報を取得し結果をfetchに返します。

//(1) "fetch"の返り値は"Promise"と呼ばれるオブジェクト
//(1) "Promise"の中身は”通信成功”もしくは”通信失敗”という結果データが入っています
//(1) さらに"Promise"には"response"が格納されており
//(1) "response"はデータベースから取得したテーブルデータなどが代入されています

//(2) ドット ”.” によるメソッドチェーンを使うことでfetchの結果である"Promise"をインスタンス化して参照することができます
//(2) thenメソッドは通信が成功した場合の処理を実行することができます
// ※  catchメソッドは通信が失敗した場合の処理を実行することができます
//(2) "Promise"を参照し内部の"response"を引数として渡すことで
//(2) "response"を"jsonファイル"として解釈した結果を返します

//(3) jsonに変換した"response”を”任意の変数”に代入することで実行する処理の中で変数を利用できるようにします
//(3) 処理の内容は取得してきたテーブルのレコードをHTMLのタグで追加する処理を実行します

//(4) コントローラーとの通信が成功した場合に実行するコードを記述する
//(4) HTMLにタグを追加するコードを記述する

//(5) コントローラーとの通信が失敗した場合に実行するコードを記述する
//(5) エラーコードやエラーメッセージなどを記述する

基本構文の省略形(意味は同じになります)

  • 処理が1行だけの場合{}returnは省略できます
fetch.js

fetch('URLを記述する第一引数') //(1)
  .then((response) => response.json()) //(2)
  .then((res) => {

                     // (3) 通信が成功した場合の実行したい処理を記述する

                  }) 

  .catch(error => {
                                //(5)
                            alert("実行失敗"); 
                            alert(error);
                        })
                    }


thenメソッドとは

参考サイト:https://www.sejuku.net/blog/52314

fetch() で通信が成功した場合のレスポンスを操作できます
ここでは通信が成功したため受け取ったレスポンスをjsonファイルに変換し
受け取ったレスポンスに存在するテーブルの情報をHTMLに反映させます

catchメソッドとは

fetch() で通信が失敗した場合のレスポンスを操作できます
alertでfetchの結果を確認すると、エラー内容が確認できます

JSONファイルとは

テキスト形式のファイルのことでJSONとはJavaScript Object Notationの略で
ジェイソンと呼ばれています。
JSONはJavaScriptで定義されているオブジェクト表記法の1つで
テキスト形式で表記されるため簡単にデータ交換ができます。
その可読性からJavaScriptに限らず主要なプログラム言語から利用されています。

メソッドチェーンとは

参考サイト:https://www.sejuku.net/blog/24962

メソッドの実行結果を変数などを代入する手間を省略し、
直接他のメソッドの引数に代入後、次のメソッドを実行することができます。

JavaScriptではメソッドを「 .」(ドット)で連結するため
fetchメソッドやの後に.thenを実行しています

Fetch関数でテーブルの一覧を表示させる

fetch関数に利用するURLを設定する

まずはfetchの通信先を設定するためにルーティングを設定します。
これでfetchメソッドの第一引数に/show_allを渡すことで
コントローラーのshowAllが実行されます

web.php
Route::get('/', 'HomeController@index')->name('crud.index'); /* 初期ページ */
Route::get('/show_all', 'HomeController@showAll'); // 全表示アクション

コントローラーのアクションにデータベースの操作処理を記述します

テーブル名:Companies
スクリーンショット 2022-12-30 9.20.27.png

コントローラーのデータベース操作処理

  1. 全てのcompaniesテーブルの全てのレコードを取得する
  2. 値はid name priceをまとめた連想配列に格納する
  3. 完成した配列はjavascriptで扱えるようにjsonデータに変換してfetchに送信する
****Controller.php

public function showAll()
{
    /* $companies = \DB::table('companies')->get(); */
    $companies = Companies::get();

    foreach($companies as $companie){
        $companieList[] = array(
          'id'    => $companie->id,
          'name'  => $companie->name,
          'price' => $companie->price
        );
    }

    // echoで配列をjsonに変換しつつfetchへサーバー情報を送信する
    echo json_encode($productList);
}

Eloquentとクエリビルダについて

参考先:https://qiita.com/Laravel-student/items/83475abb6d6acb3a177f

データベースを操作する方法にはEloquent(エロクエント)と
クエリビルダという手法がありますが、どちらでデータを取得しても
問題ありません

Eloquentの場合

// Companiesモデルを利用しデータを取得する方法です
 $products = Companies::get();
クエリビルダの場合

//DBファザードを利用しデータを取得する方法です
$companies = \DB::table('companies')->get();

fetchで実行する一覧表示の非同期処理

fetchでサーバーにリクエストを送信しましたので
サーバーから届いたレスポンスを使ってJavaScriptのコードを実行します

  • 上述のコントローラー側の処理で実行したechoメソッドが
    fetchに対して実行結果をレスポンスしています
  1. fetch関数では通信が成功した場合と失敗した場合の処理
    それぞれ記述することができます

  2. ここでは通信が成功した場合にブラウザへ表示されているHTMLに
    HTMLタグを追加する処理を実行します

fetch.js

    .then(response => response.json()) 
    .then(res => {

    /* 通信成功が成功した場合の処理 */

        // forEach はphpの繰り返し処理です "res"に存在する配列の数だけ繰り返すことができます
        // メソッドチェーンにより、"res"の値は"elm"に代入され、次からの処理はelmという連想配列を使うことができます

        // resと区別するため繰り返し処理中では連想配列の値は"elm"という配列名に代入して利用していきます
        // "elm"は"element"の略称です エレメント(要素)とは「HTMLタグ」で囲んだ情報の単位を示します
        
    res.forEach(elm =>{ 
                
                // ここにHTMLを追加する処理を記述します
                
                //目的として、データベースから取得した情報(レスポンス)を使って、<tr>、<td>タグによるレコードを挿入します
                //手段としては上述されている"index.braid.html"に存在する"result"という名前に設定したID属性の場所を取得し
                //その下層にHTMLタグを挿入します
            
        })
        alert("実行成功");
      
    })

    .catch(error => {
         // "error" は任意の変数名です 可読性を高めるためにエラーに関する変数名は"error"で統一します 
        alert("実行失敗");

        alert(error);
    })
}

// 関数を実行します
indexAll();
fetch.js

        // 取得したレコードをeachで順次取り出す
        res.forEach(elm =>{ 
                // forEach は phpの繰り返し処理 resに存在する配列の数だけ繰り返します
                // resと区別するため繰り返し処理中では連想配列の値は"elm"という配列名に代入して利用していきます
                // "elm"は"element"の略称です エレメント(要素)とは「HTMLタグ」で囲んだ情報の単位を示します
            var insertHTML = "<tr class=\"target\"><td>" + elm['id'] + "</td><td>" + elm['name'] + "</td><td>" + elm['price'] + "</td></tr>"
            var result = document.getElementById("result");
            result.insertAdjacentHTML('afterend', insertHTML);

            //メソッドチェーンで"result"に含まれる結果を参照します
            //insertAdjacentHTMLは指定したテキストを指定した場所に挿入することができます
            //第一引数は場所,第二引数はテキストになります('afterend'= 要素自身の後ろ)

        })
        alert("実行成功");
      
    })

    .catch(error => {
         // 取得したレコードをeachで順次取り出す
        alert("実行失敗");

        alert(error);
    })
}

// 関数を実行します
indexAll();
4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?