JavaScriptがわからない人のためのLaravelでのクエリー生成方法

Laravelで複数のURLパラメータを送るとき、大体の人は`<input>`を使うと思います。
自分でhtmlやcssを書く場合はそれでもいいのですが、Bootstrapを使う場合`<a>`で書いてあることが稀によくある…というかほとんどです。

それなら`<a>`で書こうとすると、複数のURLパラメータの一部を変更しようとした時、いちいちURL全部を書き直す羽目になりキリがありません。

本来はJavaScriptなどを使用してURLパラメータを自動で取得・変更してくれる機能が作れたりするらしいのですが、プログラミング初学者の方の中にはPHPしかわからない方もいらっしゃることでしょう。私もその一人です。

と言うわけで、このページでは
>JavaScriptが使えなくても遷移前のURLパラメータを維持して、さらに一部だけ変更したリンクを作成したい！

と思います。


# http_build_query
さてそんな時は[http_build_query()](https://www.php.net/manual/ja/function.http-build-query.php)を使いましょう。
この関数は配列からクエリーを自動で生成してくれるすごいやつです。

色々引数に指定することができますが、基本的には次のように使用します。

```php:
<?php 
$test_name = "first_test";

$query = array(
  'status' => 'default',
  'sort' => array(
    'start_date' => '20190518'),
    'end_date' => '20190520'),
  ),
  'search' => $test_name,
);

echo http_build_query($query);
// status=default&sort%5Bstart_date%5D=20190518&sort%5Bend_date%5D=20190520&search=first_test
// と表示されます。
```

これを利用すると次のようにクエリーを使用したaタグが簡単にかけるようになります。

```php:
<?php 
$query = array(
  'name' => '太郎',
  'age' => '20',
);

$default_url = "/mypage?";
$url_query = http_build_query($query);
$url = $default_url . $url_query;
?>

--------------（略）---------------

<a href="<?php echo $url; ?>">マイページへ</a>
<!-- /mypage?name=太郎&age=20　のページへ飛びます。 -->
```



#Laravelで使ってみる
では`http_build_query`を使って複数のURLパラメータを持ったリンクを作成してみましょう。
まずはコントローラとルートを作成します。

## ControllerとRouteの作成

```php:TestContrpller.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TestController extends Controller
{
    public function index(Request $request)
    {
        // ここにクエリーを使った処理を書く

        // ビューから受け取ったクエリーをビューに返す処理
        $url_parameter = [
            'status' => $request->status,
            'sort' => [
                'date' => $request->sort['date'],
                'time' => $request->sort['time'],
            ],
        ];

        $param = ['url_parameter' => $url_parameter];
        return view('test.index', $param);
    }
}
```

```php:web.php
Route::get('index', 'TestController@index');
```
コントローラでは`$request`で取得したクエリーを`$param`にそのまま流してるだけで、特に変わった処理はしていません。


## Viewの作成
次はビューを作成していきます。

### 初期クエリーの設定

```php:index.blade.php
{{-- 初期URLの設定 --}}
<?php $default_url = "/index?"; ?>

<?php $query = array(
  'status' => ($url_parameter['status'] ?: '0'),
  'sort' => array(
    'date' => ($url_parameter['sort']['date'] ?: '0'),
    'time' => ($url_parameter['sort']['time'] ?: '0'),
  ),
); ?>
```
まず最初にコントローラから取得した前回のクエリーを`$query`に入れます。
もしindexページへのアクセスが初回だったり、nullだった場合は`?:`で判定してデフォルト値を代入するようにしています。

### URLパラメータのstatusの値を変更するURLの生成
ここではURLパラメータのstatusの値だけを変更したURLを返す機能を作成します。

```php:index.blade.php
{{-- statusを変更するURLの生成 --}}
<p>statusパラメータの値を変更するURL</p>

<?php $status_array = array(
                        'default' => '0',
                        'start' => '10',
                        'end' => '20',
                    ); ?>

@foreach $status_array as $status_name => $status_num)
  <?php $query['status'] = $status_num; ?>

  <?php $url_query = http_build_query($query); ?>
  <?php $get_url = $default_url . $url_query; ?>
    <a href="{{ $get_url }}">status:{{ $status_name }}</a>
  <?php $get_url = ""; ?>

@endforeach

  <?php $query['status']= $url_parameter['status'] ?: '0'; ?>

<!-- /index?status=0&sort%5Bdate%5D=0&sort%5Btime%5D=0
     /index?status=10&sort%5Bdate%5D=0&sort%5Btime%5D=0
     /index?status=20&sort%5Bdate%5D=0&sort%5Btime%5D=0
     の三つのURLが生成されます。 -->
```
ここではURLを作成する際`$query`を参照しているので、前回のクエリーをそのまま引き継ぐことができます。
例えば`$query['sort']['date']`の値が`10`になっていれば、その値がここで作成されるURLにも反映されます。

### URLパラメータのsortの値を変更するURLの生成
statusと同じようにsortも作成します。

```php:index.blade.php
{{-- sort['date']を変更するURLの生成 --}}
<p>sort.dateの値を変更するURL</p>

<?php $sort_date_array = array(
                        'default' => '0',
                        'up' => '10',
                        'down' => '20',
                    ); ?>

@foreach $sort_date_array as $sort_name => $sort_num)
  <?php $query['sort']['date'] = $status_num; ?>

  <?php $url_query = http_build_query($query); ?>
  <?php $get_url = $default_url . $url_query; ?>
    <a href="{{ $get_url }}">sort.date:{{ $sort_name }}</a>
  <?php $get_url = ""; ?>

@endforeach

  <?php $query['sort']['date']= $url_parameter['sort']['date'] ?: '0'; ?>


{{-- sort['time']を変更するURLの生成 --}}
<p>sort.timeの値を変更するURL</p>

<?php $sort_time_array = array(
                        'default' => '0',
                        'up' => '10',
                        'down' => '20',
                    ); ?>

@foreach $sort_time_array as $sort_name => $sort_num)
  <?php $query['sort']['time'] = $sort_num; ?>

  <?php $url_query = http_build_query($query); ?>
  <?php $get_url = $default_url . $url_query; ?>
    <a href="{{ $get_url }}">sort.time:{{ $sort_name }}</a>
  <?php $get_url = ""; ?>

@endforeach

  <?php $query['sort']['time']= $url_parameter['sort']['time'] ?: '0'; ?>
```
変数の名前などが変わっただけで、statusの方とやっていることは同じです。

# 最後に
コードだけではわかりづらいと思うので、適当にリンク押してURLのクエリーがコロコロ変わる様子を見てみてください。
そうすればどうゆうことをやっているのか理解できるかと思います。

ちなみにですが`<form avtion="">`内に上記の`$get_url`を入れれば、URLパラメータを維持したまま`<input>`を使ったgetメソッドも使うことができるので、検索フォームなどを作成したい場合はそちらも試してみてください。

## 参考文献
[PHPマニュアル:http_build_query](https://www.php.net/manual/ja/function.http-build-query.php)