29.

PHP GET 通信完全ガイド(curl / Laravel HTTP / Guzzle / fetch / Postman)

編集
この記事の要点
  • GET 通信は URL にクエリ文字列を付けて取得する HTTP メソッド。冪等で副作用なし
  • PHP 側で受け取り: $_GET["param"]、Laravel は $request->query() / $request->input()
  • 送信は curl (CURLOPT_URL) / Laravel Http::get() / Guzzle / file_get_contents
  • 配列パラメータは ?ids[]=1&ids[]=2、URL エンコードは http_build_query() が安全
  • CORS / Origin ヘッダの理解、Postman / curl での再現確認、fetch / axios でのフロント連携

GET 通信とは

HTTP の代表的なメソッドの一つで、サーバから情報を取得するのが本来の用途です。URL に ?key=value&key2=value2 形式でクエリ文字列を付与して送信し、サーバ側で読み取ります。

性質説明
冪等性何度同じリクエストを送っても結果が変わらない(基本)
キャッシュ可能ブラウザ / CDN がキャッシュする
ボディ無し(実質)パラメータは URL に乗せる
URL 長制限サーバ・ブラウザによるが約 2000〜8000 文字
機密データ不向きURL がブラウザ履歴 / アクセスログに残る

PHP 側で受け取る

<?php
// http://example.com/search.php?q=php&page=2

// シンプルな取得
$q    = $_GET['q'] ?? '';
$page = (int)($_GET['page'] ?? 1);

// バリデーション
$q = mb_substr(trim($q), 0, 100);
if ($page < 1) $page = 1;

// 配列パラメータ ?ids[]=1&ids[]=2&ids[]=3
$ids = $_GET['ids'] ?? [];
$ids = array_filter($ids, fn($v) => ctype_digit((string)$v));

// 全クエリを連想配列で
print_r($_GET);
// Array ( [q] => php [page] => 2 [ids] => Array ( [0] => 1 [1] => 2 ) )

// REQUEST_URI から自前パース
$urlParts = parse_url($_SERVER['REQUEST_URI']);
parse_str($urlParts['query'] ?? '', $params);

Laravel での受け取り

use Illuminate\Http\Request;

Route::get('/search', function (Request $request) {
    // query() はクエリ文字列のみ、input() は POST/GET 両対応
    $q    = $request->query('q', '');
    $page = (int) $request->query('page', 1);

    // 検証付き
    $validated = $request->validate([
        'q'    => 'nullable|string|max:100',
        'page' => 'integer|min:1|max:1000',
        'ids'  => 'array',
        'ids.*'=> 'integer',
    ]);

    return view('search.index', compact('q', 'page'));
});

// FormRequest 化
class SearchRequest extends FormRequest {
    public function rules(): array {
        return [
            'q'    => 'nullable|string|max:100',
            'page' => 'integer|min:1',
        ];
    }
}

curl で GET 送信(PHP 内から)

<?php
function httpGet(string $url, array $params = [], array $headers = []): array {
    if ($params) {
        $url .= (str_contains($url, '?') ? '&' : '?') . http_build_query($params);
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_MAXREDIRS      => 3,
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_HTTPHEADER     => array_merge([
            'Accept: application/json',
            'User-Agent: MyApp/1.0',
        ], $headers),
    ]);

    $body   = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err    = curl_error($ch);
    curl_close($ch);

    if ($body === false) {
        throw new RuntimeException("curl error: $err");
    }
    return ['status' => $status, 'body' => $body];
}

// 利用
$resp = httpGet('https://api.example.com/users', ['page' => 1, 'per_page' => 20]);
$data = json_decode($resp['body'], true);

Laravel HTTP Client

Laravel 7+ には Guzzle ベースの Http ファサードが入っています。最も読みやすい書き方です:

use Illuminate\Support\Facades\Http;

// 基本
$response = Http::get('https://api.example.com/users', [
    'page' => 1,
    'per_page' => 20,
]);

if ($response->successful()) {
    $data = $response->json();
}

// ヘッダ / タイムアウト / リトライ / 認証
$response = Http::withHeaders([
        'Accept-Language' => 'ja',
    ])
    ->withToken($token)            // Authorization: Bearer
    ->timeout(10)
    ->retry(3, 200)                // 3 回、200ms 間隔
    ->get('https://api.example.com/users', ['q' => 'php']);

// マクロ / プール(並列)
$responses = Http::pool(fn ($pool) => [
    $pool->get('https://api.example.com/a'),
    $pool->get('https://api.example.com/b'),
]);

Guzzle 直接利用

use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;

$client = new Client([
    'base_uri' => 'https://api.example.com',
    'timeout'  => 10,
    'http_errors' => false,           // 4xx/5xx で例外を投げない
]);

try {
    $response = $client->get('/users', [
        'query' => [
            'page' => 1,
            'ids'  => [10, 20, 30],     // ?ids[0]=10&ids[1]=20&ids[2]=30
        ],
        'headers' => ['Accept' => 'application/json'],
    ]);
    $data = json_decode((string)$response->getBody(), true);
} catch (GuzzleException $e) {
    error_log($e->getMessage());
}

配列・ネストの送信

<?php
// http_build_query が PHP 5.1.3+ で標準
$params = [
    'q'       => 'php',
    'ids'     => [1, 2, 3],
    'filter'  => [
        'category' => 'book',
        'price'    => ['min' => 100, 'max' => 5000],
    ],
];

$qs = http_build_query($params);
// q=php
// &ids%5B0%5D=1&ids%5B1%5D=2&ids%5B2%5D=3
// &filter%5Bcategory%5D=book
// &filter%5Bprice%5D%5Bmin%5D=100&filter%5Bprice%5D%5Bmax%5D=5000

// 区切りを「&」「&」のどちらにするか
http_build_query($params, '', '&', PHP_QUERY_RFC3986);

URL エンコードの違い

関数挙動用途
urlencode()スペース → +application/x-www-form-urlencoded
rawurlencode()スペース → %20RFC 3986 準拠(パスや一般的な URL)
http_build_query()連想配列を一括変換(既定 PHP_QUERY_RFC1738)クエリ文字列生成

CORS(クロスオリジン)の理解

ブラウザの JS から別オリジンの API を GET する場合、サーバ側でCORS ヘッダを返す必要があります:

<?php
// シンプル GET の場合
header('Access-Control-Allow-Origin: https://app.example.com');
header('Vary: Origin');

// 認証情報付き(Cookie)
header('Access-Control-Allow-Credentials: true');
// → JS 側は fetch(url, { credentials: 'include' })

// Preflight (OPTIONS) が来るのは
// - 独自ヘッダがある
// - PUT/DELETE/PATCH
// - Content-Type が application/json

JS との連携(fetch / axios)

// fetch API
const params = new URLSearchParams({ q: 'php', page: 2 });
fetch(`/api/search?${params}`, {
  headers: { Accept: 'application/json' },
})
  .then(r => r.json())
  .then(data => console.log(data));

// axios
import axios from 'axios';
const { data } = await axios.get('/api/search', {
  params: { q: 'php', page: 2, ids: [1, 2, 3] },
  paramsSerializer: { indexes: false },  // ?ids=1&ids=2 形式
});

Postman / curl での検証

# curl で GET
curl -G https://api.example.com/users \
  -H "Accept: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  --data-urlencode "q=php" \
  --data-urlencode "page=2"

# ヘッダも表示
curl -i 'https://api.example.com/users?q=php'

# 詳細トレース
curl -v 'https://api.example.com/users?q=php'

# レスポンスを保存
curl -o out.json 'https://api.example.com/users'

Postman では Params タブにキー / バリューを追加すれば自動で URL にクエリが反映されます。Auth タブで Bearer Token、Headers タブでカスタムヘッダを設定。

注意点とアンチパターン

  • パスワード / トークンを GET で送らない → アクセスログに残る
  • 長い URL は 414 URI Too Long を引き起こす
  • GET で副作用(DB 更新)を起こすとブラウザ プリフェッチで意図せず実行される
  • $_GET['param']直接 SQL に埋め込まない → プリペアド文に渡す
  • XSS 防止のため、出力時は htmlspecialchars() + ホワイトリスト検証

FAQ

Q: GET の上限文字数は?
A: ブラウザは 2000〜8000 程度を保証、サーバは Nginx の large_client_header_buffers で調整。大きいデータは POST + body を使う。

Q: GET と POST どちらを使うべき?
A: 取得のみ → GET状態変更 → POST/PUT/DELETE。RESTful 設計が API のキャッシュ性能を上げます。

Q: 同じパラメータ名を複数回送ると?
A: ?id=1&id=2$_GET['id'] に最後の値「2」だけが入ります。配列にするには ?id[]=1&id[]=2

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 基本事項
  2. HTMLへの埋め込み
  3. 変数
  4. 可変変数
  5. 定数
  6. データ型
  7. キャスト
  8. エスケープ文字
  9. 配列
  10. 演算子
  11. 代入の際の注意点
  12. 条件分岐
  13. 繰り返し処理
  14. クラスとインスタンス
  15. コンストラクタ
  16. 関数
  17. スーパーグローバル変数
  18. スコープ
  19. staticについて
  20. yieldについて
  21. ファイルのアップロード方法
  22. DB接続方法
  23. SQL実行方法
  24. カプセル化の具体例
  25. 継承の構文
  26. オーバーライド
  27. ポリモーフィズム(多様性)の具体例
  28. 抽象クラス・メソッドの構文と具体例
  29. GET通信
  30. try catchで全てのエラーを拾う方法

最近更新/作成されたページ