WebページのURL設計で考えること

Tag:

WebページのURL設計をする際、どういったことを考える必要があるのか紹介します。

※PHPのフレームワークである「Laravel」を例にURL設計を実装する方法についても取り上げます。

WebAPI向けのURL設計については、書籍などで詳しく取り上げられています。WebページのURL設計も、基本はWebAPIのURL設計で取り上げられる「リソース指向」が中心となります。リソース指向で考えることで推測しやすいURLを設計することができます。

リソースを中心に考える

URLはリソースを識別する名詞にします。

ブログ記事を例に考えると以下のようになります。

※ブログ記事一覧
/post

※プログ記事ページ
/post/100

リソースに従属するリソースもあります。
・ブログ記事は、カテゴリに属する。
・ブログ記事には、コメントが複数付く。
このような場合、階層形式にします。

/category/post/100/comment

ブログ記事に従属するコメント情報は「/category/post/100」で表示することが多いかと思います。このとき、

・コメント情報も「/category/post/100」にアクセスする際に取得する場合
⇒「/category/post/100/comment」に対するHTTPメソッドとして
「POST, PUT, DELETE」が必要となるかと思います。
・コメント情報をajaxで別途取得する場合
⇒「/category/post/100/comment」に対するHTTPメソッドとして
「GET, POST, PUT, DELETE」が必要となるかと思います。

リソースに対する操作

リソースに対する操作(取得、作成、更新、削除)はURLで指定せず、HTTPメソッドで指定します。

HTTPメソッド 役割
GET リソース取得
POST リソース作成
PUT リソース更新
DELETE リソース削除

HTMLのFORMは、PUT、DELETEメソッドをサポートしていません。そのため、LaravelでPUT、DELETEメソッドを指定するには「_method隠しフィールド」を利用します。

<form action="{{ url('/post/' . $post_id) }}" method="POST">
    <input type="hidden" name="_method" value="PUT">
</form>

リソース作成ページ、更新ページ

Webページの場合、リソースを作成するためのページ、更新するためのページとして別途URLが必要となることが多いです。

リソースの一覧ページで、ボタンをクリックするとモーダルが表示され、そこで更新させるといった実装方法もあります。この場合、更新用に別途URLを用意する必要はありません。

Laravelのリソースフルコントローラーでは、以下のように対応しています。

HTTPメソッド URL 役割
GET /post リソースの一覧ページを表示
GET /post/create リソースを新規作成するためのページを表示
POST /post リソースを新規作成
GET /post/{post} 指定されたリソースの詳細情報を表示
GET /post/{post}/edit 指定されたリソースを更新するためのページを表示
PUT/PATCH /post/{post} 指定されたリソースを更新
PUT:指定された情報を更新する
PATCH:指定された情報を部分的に更新する
DELETE /post/{post} 指定されたリソースを削除

「/post/create」でリソース作成画面を取得し、「/post/{post}/edit」でリソース更新画面を取得してます。URLは名詞であることが原則ですが、こういった例外もあります。

この他に確認画面なども必要となる場合があります。
そのときは、「/post/{post}/confirmation」などがよいかと思います。

1リソースに対する複数の出力表現

下記のように、1つのリソースに対して必要となる出力表現は複数あります。

端末:スマホ用の出力、デスクトップ用の出力
言語:日本語表示、英語表示など
フォーマット:html、jsonなど
ユーザー種類:管理者向けの出力、一般ユーザー向けの出力

1つずつ判別する方法例を紹介します。

端末

URL:/post/{post}
HTTP要求ヘッダーのUser-Agentで端末判定

言語

URL:/post/{post}?hl=en

HTTP要求ヘッダーのAccept-Languageで言語を指定することもできます。しかし、クライアントがブラウザで設定変更する必要があります。そのためAccept-Languageで判定せず、パラメータで言語判定するようにしました。hlは「hreflang」の略です。

フォーマット

方法1 拡張子で判定

URL:/post/{post}.json

方法2 Acceptヘッダーで判定

URL:/post/{post}
HTTP要求ヘッダーのAcceptでフォーマット判定

クライアントは、HTTP要求ヘッダーのAcceptでどのフォーマットであれば受け入れ可能であるか伝えることができます。

※Acceptの例
Accept:"application/json, text/javascript, */*; q=0.01"
Accept:"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"

サーバーは、HTTP応答ヘッダーのContent-Typeでどのフォーマットを使用しているか伝えることができます。

※Content-Typeの例
Content-Type:"application/json"
Content-Type:"text/html; charset=UTF-8"

Laravelでは、以下のようにAcceptヘッダーを判別することができます。

if (Request::format() === 'json') {
    //
} else if (Request::format() === 'html') {

}

ユーザー種類

色々な方法があり、どれが適しているとも言いずらいので一番悩みます。とりあえず、「URLを同じにするのか」、「URLを分けるのか」で大きく分かれるのかと思います。

方法1 URLは同じ

※一般ユーザー、管理者
URL:/post/{post}

方法2 URLを分ける

※一般ユーザー
URL:/post/{post}

※管理者
URL:/admin/post/{post}

検索結果ページ

Webページには検索機能がつきものです。検索は「全体からの検索」と「リソースからの検索」で分けるとよいかと思います。

※サイト全体からの検索
/search?name=yamada

※リソースからの検索
/user?q=yamada

HTTPステータスコード

HTTPステータスコードを決める際に、下記サイトがとても参考になりました。
http://postd.cc/choosing-an-http-status-code/

URL設計で参考になる本

URL設計に関する本として有名な本を紹介します。

RESTful Webサービス


この本の中で紹介されている設計手順について参考にすることが多いです。

手順 作業
1 Webサービスで提供するデータを特定する
2 データをリソースに分ける
3 リソースにURIで名前を付ける
4 クライアントに提供するリソースの表現を設計する
5 リンクとフォームを利用してリソース同士を結び付ける
6 イベントの標準的なコースを検討する
7 エラーについて検討する

Webを支える技術

スポンサーリンク