現在のインターネットエコシステムはAPIによって完全に変更されており、正当な理由があります。製品またはサービスでサードパーティAPIを使用することにより、認証やストレージサービスなど、幅広い有用な機能にアクセスできます。これは、あなたとユーザーにとって有益です。独自のAPIを公開することにより、アプリケーションは「構成の一部」になり、これを考えたことのない方法で使用します...もちろん、これを正しい方法で行うと。この2部構成のシリーズでは、一連の実際のベストプラクティスを使用して、PHPアプリケーション用のRESTFUL APIレイヤーを作成する方法を紹介します。このプロジェクトの完全なソースコードは、パート2の終わりに提供されます。
キーポイント
まず、APIは開発者のユーザーインターフェイスであるため、フレンドリーでシンプルで使いやすく、もちろん快適でなければなりません。単純だがよく書かれたreadmeファイルであっても、ドキュメントは良いスタートです。必要な情報が最も少ないのは、サービススコープの概要と、メソッドとアクセスポイントのリストです。適切な要約は、次のようになります。>連絡先とメモの2つのオブジェクトタイプがあります。各連絡先には、名、姓、メールアドレスなどの基本的な属性があります。さらに、各連絡先は、それに関連付けられたマークダウン形式の複数のノートを持つことができます。
次に、実装するすべてのリソースと操作をリストする方が良いでしょう。これは、アプリケーションのワイヤーフレームを視覚化するのに相当するものと見なすことができます。休息の主要な原則に従って、各リソースは、操作がアクセスに使用されるHTTPメソッドであるURLで表されます。たとえば、Get/API/CONTACTS/12はID 12との連絡先を取得し、Put/API/CONTACTS/12は同じ連絡先を更新します。完全なメソッドリストは次のとおりです
<code>URL HTTP Method Operation /api/contacts GET 返回联系人数组 /api/contacts/:id GET 返回 ID 为 :id 的联系人 /api/contacts POST 添加一个新联系人并返回它(添加了 id 属性) /api/contacts/:id PUT 更新 ID 为 :id 的联系人 /api/contacts/:id PATCH 部分更新 ID 为 :id 的联系人 /api/contacts/:id DELETE 删除 ID 为 :id 的联系人 /api/contacts/:id/star PUT 将 ID 为 :id 的联系人添加到收藏夹 /api/contacts/:id/star DELETE 从收藏夹中删除 ID 为 :id 的联系人 /api/contacts/:id/notes GET 返回 ID 为 :id 的联系人的笔记 /api/contacts/:id/notes/:nid GET 返回 ID 为 :id 的联系人的 ID 为 :nid 的笔记 /api/contacts/:id/notes POST 为 ID 为 :id 的联系人添加新笔记 /api/contacts/:id/notes/:nid PUT 更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记 /api/contacts/:id/notes/:nid PATCH 部分更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记 /api/contacts/:id/notes/:nid DELETE 删除 ID 为 :id 的联系人的 ID 为 :nid 的笔记</code>
より完全で専門的なドキュメントについては、Swagger、Apidoc、Google Apis Discovery Serviceなどのツールを使用することを検討できます。ユーザーはあなたを好むでしょう!
ツールと設定
APIの構築に使用する主なツールは、スリムなフレームワークです。なぜ? &gt;
これは本当です。その強力なルーティング機能により、取得と投稿以外の使用方法を簡単に使用できます。HTTPメソッドオーバーライド(HTTPヘッダーと非表示のポストフィールドを介して)の組み込みサポートを提供し、アプリケーションプログラムとAPIを有効にするためのミドルウェアと追加機能をフックできます。開発は本当に簡単です。 Slimと一緒に、イディオームを使用してデータベースレイヤーにアクセスし、モノログを使用してロギングします。したがって、composer.jsonファイルは次のようになります
{ "name": "yourname/my-contacts", "description": "Simple RESTful API for contacts management", "license": "MIT", "authors": [ { "name": "Your Name", "email": "you@yourdomain.com" } ], "require": { "slim/slim": "*", "slim/extras": "*", "slim/middleware": "*", "monolog/monolog": "*", "j4mie/paris": "*", "flynsarmy/slim-monolog": "*" }, "archive": { "exclude": ["vendor", ".DS_Store", "*.log"] }, "autoload": { "psr-0": { "API": "lib/" } } }
アプリケーションのフロントエンドコントローラーはpublic/index.phpであり、すべての非ファイルまたはディレクトリトラフィックは、標準のURL書き換えルールを介してここでリダイレクトされます。次に、すべての初期化コードをbootstrap.phpに入れて、後で表示されます。共有ディレクトリには、ログ、構成ファイル、SQLiteデータベース、ダンプファイル、SSL証明書などのデータが含まれています。 BINディレクトリには、提供された.SQLファイルを使用してデータベースを作成し、データをインポートするユーティリティスクリプトが含まれています。
<code>bootstrap.php composer.json README.md bin/ import install lib/ API/ public/ .htaccess index.php share/ config/ default.php db/ logs/ sql/ data/ contacts.sql users.sql tables/ contacts.sql notes.sql users.sql ssl/ mysitename.crt mysitename.key</code>
sslはどこにでもあります
最初にディレクトリ設定を定義して、サイトのHTTPバージョンとHTTPSバージョンに共通するようにします。非セキュアなホスト構成では、mod_rewriteを使用して、任意の非セキュア接続に403の禁止エラーを発行し、セキュリティセクションで、自己署名証明書でSSLを設定し、SLIM_ENV変数を伝えるSLIM_ENV変数を設定します。現在のアプリケーションモードをスリムします。 Apacheの自己署名証明書を作成してインストールする方法の詳細については、SSLShopperのこの記事を参照してください。明確な目標、基本的なディレクトリ構造、サーバー設定ができるようになったので、Composer.pharのインストールを実行して、コードの書き込みを開始します。
<Directory> # Required for mod_rewrite in .htaccess AllowOverride FileInfo Options All -Indexes DirectoryIndex index.php index.shtml index.html <IfModule php5_module=""> # For Development only! php_flag display_errors On </IfModule> # Enable gzip compression <IfModule filter_module=""> AddOutputFilterByType DEFLATE application/json </IfModule> Order deny,allow Deny from all Allow from 127.0.0.1 </Directory> <VirtualHost *:80> ServerAdmin you@yourdomain.com DocumentRoot "/path/to/MyApp/public" ServerName myapp.dev <IfModule rewrite_module=""> RewriteEngine on ## Throw a 403 (forbidden) status for non secure requests RewriteCond %{HTTPS} off RewriteRule ^.*$ - [L,R=403] </IfModule> </VirtualHost> <IfModule ssl_module=""> NameVirtualHost *:443 Listen 443 SSLRandomSeed startup builtin SSLRandomSeed connect builtin <VirtualHost *:443> ServerAdmin you@yourdomain.com DocumentRoot "/path/to/MyApp/public" ServerName myapp.dev SSLEngine on SSLCertificateFile /path/to/MyApp/share/ssl/mysitename.crt SSLCertificateKeyFile /path/to/MyApp/share/ssl/mysitename.key SetEnv SLIM_MODE development </VirtualHost> </IfModule>
ブートプログラムとフロントエンドコントローラー
前述のように、Bootstrap.phpファイルは、アプリケーション設定とオートローダー設定をロードする責任があります。 最初に、現在の環境を取得します。 app/path/share/logs/envname_yyy-mm-dd.logのファイルに書き込むモノログロガーを構成します。次に、いくつかの改善の後(ソースコードで表示できます)、生成されたログライターを取得し、データベースに接続しようとします。
ルーティング構造
jsonミドルウェア
ルートパスをミドルウェアコンストラクターに渡すことができます。この場合、ミドルウェアがサイトのAPI部分にのみ適用されるように、 /API /V1を渡します。現在のパスが応答コンテンツタイプのヘッダーと一致する場合、応答コンテンツタイプのヘッダーはアプリケーション/JSONに強制され、リクエスト方法を確認します。要求方法が書き込みを有効にするリクエストメソッドの1つである場合(Put、Post、Patch)、リクエストコンテンツタイプのヘッダーはApplication/JSONでなければなりません。すべてが正常に機能する場合、ステートメント$ this&gt; next&gt; call()は、チェーン内の次のミドルウェアを実行します。 認証 アプリケーションはデフォルトでHTTPSで実行されるため、基本認証よりもトークンが優先される方法を使用することにしました。APIキーは、基本的なHTTP認証ヘッダーのユーザー名フィールドに送信されます(パスワードは不要))。これを行うために、既存のSlim httpbasicauthを変更することにより、Tokenoverbasicauthというスリムミドルウェアクラスを書きました。このミドルウェアはチェーンで最初に実行されるため、最後のものとして追加され、コンストラクターにオプションのルートパスパラメーターが必要です。
APIは、可能であれば、使用可能な形式、できればJSON表現で有用なエラーメッセージを表示する必要があります。エラーコードとメッセージを含む最小ペイロードが必要です。さらに、検証エラーはより多くのセグメンテーションが必要です。 Slimを使用して、それぞれ$ app-&gt; notfound()および$ app-&gt; error()メソッドを使用して、404エラーとサーバーエラーを再定義できます。 エラーはより単純ではありません:最初に要求されたメディアタイプを取得し、次に$ ISAPIフラグが現在のURLが /API /V*グループにあるかどうかを教えてくれます。クライアントがAPI URLを要求するか、JSONコンテンツタイプのヘッダーを送信した場合、JSON出力を返します。そうしないと、この例に示すようにテンプレートをレンダリングするか、静的HTMLを印刷できます。他のエラーは少し注意が必要であり、$ app-&gt; error()メソッドが例外が発生したときにトリガーされ、標準のPHPエラーをErrorexceptionオブジェクトに変換します。セキュリティの脆弱性を回避するために、あまりにも多くの内部メカニズムを公開することなく、クライアントに有用なエラーを提供する方法が必要です。このアプリケーションでは、2つのカスタム例外、ApiexceptionとapiexceptionValidationExceptionを作成しました。これらは一般に公開されます。他のすべての例外タイプはログにログに記録され、開発モードでのみ表示されます。 $ app-&gt; error()メソッドは、スローされた例外をパラメーターとして受信します。デフォルトでは、必要なすべてのデータを取得して$エラーアレイを入力します。その後、生産モードの場合は、プライベートデータを設定し、一般的なデータでメッセージを書き直します。 Custom ValidationExceptionクラスには、最終的なペイロードに追加された一連の検証エラーを返すカスタムgetData()メソッドがあります。次に、リクエストに基づいてJSONまたはHTMLにエラーを表示します。 API側では、次のように簡単なエラーが発生します。
結論
FAQ(FAQ)のゼロからの休憩の構築に関する
REST APIでの正しいエラー処理により、その使いやすさと信頼性が向上します。 HTTPステータスコードを使用して、エラータイプを示します。エラーの詳細については、応答本体にエラーメッセージを含めてください。これにより、クライアントは何が間違っているのか、どのように問題を解決するかを理解するのに役立ちます。 REST APIをテストして、期待どおりに機能し、さまざまなシナリオを処理できることを確認します。手動テストには、PostmanやCurlなどのツールを使用できます。自動テストについては、単体テスト、統合テスト、およびエンドツーエンドテストの使用を検討してください。モックサーバーを使用してAPI応答をシミュレートし、APIがさまざまな種類の応答を処理する方法をテストします。 優れたドキュメントにより、REST APIが理解し、使用しやすくなります。エンドポイント、要求方法、要求パラメーター、リクエスト例、応答ステータスコード、および応答の例に関する詳細情報が含まれています。 SwaggerやPostmanなどのツールを使用して、APIドキュメントを生成およびホストすることができます。 設計RESTFUL APIには、リソース、エンドポイント、およびメソッドの計画が含まれます。リソースには名詞と操作にはHTTPメソッドを使用します。 APIをシンプルで直感的に保ちます。ステータスコードを使用して、リクエストの結果を示します。 APIのステートレスを作成します。つまり、各リクエストには、リクエストを処理するために必要なすべての情報が含まれている必要があります。 ページングは、単一の応答で返されるデータの量を制限するのに役立ちます。 「ページ」や「制限」などのクエリパラメーターを使用してページングを実装できます。応答ヘッダーまたはボディにメタデータを含めて、現在のページ、ページの総数、アイテムの総数などを示します。 レート制限は、REST APIを乱用から保護し、公正な使用を保証します。 IPアドレス、APIキー、またはユーザーアカウントに基づいてリクエストの数を制限できます。 HTTPヘッダーを使用して、クライアントにレート制限ステータスを通知します。 REST APIをサーバーまたはクラウドプラットフォームに展開できます。展開オプションを選択するときは、コスト、スケーラビリティ、セキュリティなどの要因を考慮してください。展開プロセスを自動化するために、継続的な統合と継続的配信(CI/CD)ツールを使用します。 APIのパフォーマンスと使用量を監視して、ユーザーのニーズを満たしていることを確認します。 以上がゼロからREST APIを構築する:はじめにの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。<code>URL HTTP Method Operation
/api/contacts GET 返回联系人数组
/api/contacts/:id GET 返回 ID 为 :id 的联系人
/api/contacts POST 添加一个新联系人并返回它(添加了 id 属性)
/api/contacts/:id PUT 更新 ID 为 :id 的联系人
/api/contacts/:id PATCH 部分更新 ID 为 :id 的联系人
/api/contacts/:id DELETE 删除 ID 为 :id 的联系人
/api/contacts/:id/star PUT 将 ID 为 :id 的联系人添加到收藏夹
/api/contacts/:id/star DELETE 从收藏夹中删除 ID 为 :id 的联系人
/api/contacts/:id/notes GET 返回 ID 为 :id 的联系人的笔记
/api/contacts/:id/notes/:nid GET 返回 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes POST 为 ID 为 :id 的联系人添加新笔记
/api/contacts/:id/notes/:nid PUT 更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes/:nid PATCH 部分更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes/:nid DELETE 删除 ID 为 :id 的联系人的 ID 为 :nid 的笔记</code>
{
"name": "yourname/my-contacts",
"description": "Simple RESTful API for contacts management",
"license": "MIT",
"authors": [
{
"name": "Your Name",
"email": "you@yourdomain.com"
}
],
"require": {
"slim/slim": "*",
"slim/extras": "*",
"slim/middleware": "*",
"monolog/monolog": "*",
"j4mie/paris": "*",
"flynsarmy/slim-monolog": "*"
},
"archive": {
"exclude": ["vendor", ".DS_Store", "*.log"]
},
"autoload": {
"psr-0": {
"API": "lib/"
}
}
}
<code>bootstrap.php
composer.json
README.md
bin/
import
install
lib/
API/
public/
.htaccess
index.php
share/
config/
default.php
db/
logs/
sql/
data/
contacts.sql
users.sql
tables/
contacts.sql
notes.sql
users.sql
ssl/
mysitename.crt
mysitename.key</code>
<Directory>
# Required for mod_rewrite in .htaccess
AllowOverride FileInfo
Options All -Indexes
DirectoryIndex index.php index.shtml index.html
<IfModule php5_module="">
# For Development only!
php_flag display_errors On
</IfModule>
# Enable gzip compression
<IfModule filter_module="">
AddOutputFilterByType DEFLATE application/json
</IfModule>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Directory>
<VirtualHost *:80>
ServerAdmin you@yourdomain.com
DocumentRoot "/path/to/MyApp/public"
ServerName myapp.dev
<IfModule rewrite_module="">
RewriteEngine on
## Throw a 403 (forbidden) status for non secure requests
RewriteCond %{HTTPS} off
RewriteRule ^.*$ - [L,R=403]
</IfModule>
</VirtualHost>
<IfModule ssl_module="">
NameVirtualHost *:443
Listen 443
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
<VirtualHost *:443>
ServerAdmin you@yourdomain.com
DocumentRoot "/path/to/MyApp/public"
ServerName myapp.dev
SSLEngine on
SSLCertificateFile /path/to/MyApp/share/ssl/mysitename.crt
SSLCertificateKeyFile /path/to/MyApp/share/ssl/mysitename.key
SetEnv SLIM_MODE development
</VirtualHost>
</IfModule>
私の最初のアプローチは、認証とJSONリクエスト /応答のために /V1グループ内でルーティングミドルウェア(別のスリムミドルウェア)を使用することでしたが、クラシックミドルウェアを使用するためにより実用的で簡潔であることがわかりました。前述のように、ミドルウェアは、Slimmiddlewareから継承されたクラスのインスタンスです。スリムミドルウェアのcall()メソッドは、操作がグローバルミドルウェアとしてリンクされている場合、$ app-&gt; add()メソッドを使用して自動的に実行されます。
<code>URL HTTP Method Operation
/api/contacts GET 返回联系人数组
/api/contacts/:id GET 返回 ID 为 :id 的联系人
/api/contacts POST 添加一个新联系人并返回它(添加了 id 属性)
/api/contacts/:id PUT 更新 ID 为 :id 的联系人
/api/contacts/:id PATCH 部分更新 ID 为 :id 的联系人
/api/contacts/:id DELETE 删除 ID 为 :id 的联系人
/api/contacts/:id/star PUT 将 ID 为 :id 的联系人添加到收藏夹
/api/contacts/:id/star DELETE 从收藏夹中删除 ID 为 :id 的联系人
/api/contacts/:id/notes GET 返回 ID 为 :id 的联系人的笔记
/api/contacts/:id/notes/:nid GET 返回 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes POST 为 ID 为 :id 的联系人添加新笔记
/api/contacts/:id/notes/:nid PUT 更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes/:nid PATCH 部分更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes/:nid DELETE 删除 ID 为 :id 的联系人的 ID 为 :nid 的笔记</code>
{
"name": "yourname/my-contacts",
"description": "Simple RESTful API for contacts management",
"license": "MIT",
"authors": [
{
"name": "Your Name",
"email": "you@yourdomain.com"
}
],
"require": {
"slim/slim": "*",
"slim/extras": "*",
"slim/middleware": "*",
"monolog/monolog": "*",
"j4mie/paris": "*",
"flynsarmy/slim-monolog": "*"
},
"archive": {
"exclude": ["vendor", ".DS_Store", "*.log"]
},
"autoload": {
"psr-0": {
"API": "lib/"
}
}
}
<code>bootstrap.php
composer.json
README.md
bin/
import
install
lib/
API/
public/
.htaccess
index.php
share/
config/
default.php
db/
logs/
sql/
data/
contacts.sql
users.sql
tables/
contacts.sql
notes.sql
users.sql
ssl/
mysitename.crt
mysitename.key</code>
<code>URL HTTP Method Operation
/api/contacts GET 返回联系人数组
/api/contacts/:id GET 返回 ID 为 :id 的联系人
/api/contacts POST 添加一个新联系人并返回它(添加了 id 属性)
/api/contacts/:id PUT 更新 ID 为 :id 的联系人
/api/contacts/:id PATCH 部分更新 ID 为 :id 的联系人
/api/contacts/:id DELETE 删除 ID 为 :id 的联系人
/api/contacts/:id/star PUT 将 ID 为 :id 的联系人添加到收藏夹
/api/contacts/:id/star DELETE 从收藏夹中删除 ID 为 :id 的联系人
/api/contacts/:id/notes GET 返回 ID 为 :id 的联系人的笔记
/api/contacts/:id/notes/:nid GET 返回 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes POST 为 ID 为 :id 的联系人添加新笔记
/api/contacts/:id/notes/:nid PUT 更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes/:nid PATCH 部分更新 ID 为 :id 的联系人的 ID 为 :nid 的笔记
/api/contacts/:id/notes/:nid DELETE 删除 ID 为 :id 的联系人的 ID 为 :nid 的笔记</code>
{
"name": "yourname/my-contacts",
"description": "Simple RESTful API for contacts management",
"license": "MIT",
"authors": [
{
"name": "Your Name",
"email": "you@yourdomain.com"
}
],
"require": {
"slim/slim": "*",
"slim/extras": "*",
"slim/middleware": "*",
"monolog/monolog": "*",
"j4mie/paris": "*",
"flynsarmy/slim-monolog": "*"
},
"archive": {
"exclude": ["vendor", ".DS_Store", "*.log"]
},
"autoload": {
"psr-0": {
"API": "lib/"
}
}
}
<code>bootstrap.php
composer.json
README.md
bin/
import
install
lib/
API/
public/
.htaccess
index.php
share/
config/
default.php
db/
logs/
sql/
data/
contacts.sql
users.sql
tables/
contacts.sql
notes.sql
users.sql
ssl/
mysitename.crt
mysitename.key</code>
<Directory>
# Required for mod_rewrite in .htaccess
AllowOverride FileInfo
Options All -Indexes
DirectoryIndex index.php index.shtml index.html
<IfModule php5_module="">
# For Development only!
php_flag display_errors On
</IfModule>
# Enable gzip compression
<IfModule filter_module="">
AddOutputFilterByType DEFLATE application/json
</IfModule>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Directory>
<VirtualHost *:80>
ServerAdmin you@yourdomain.com
DocumentRoot "/path/to/MyApp/public"
ServerName myapp.dev
<IfModule rewrite_module="">
RewriteEngine on
## Throw a 403 (forbidden) status for non secure requests
RewriteCond %{HTTPS} off
RewriteRule ^.*$ - [L,R=403]
</IfModule>
</VirtualHost>
<IfModule ssl_module="">
NameVirtualHost *:443
Listen 443
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
<VirtualHost *:443>
ServerAdmin you@yourdomain.com
DocumentRoot "/path/to/MyApp/public"
ServerName myapp.dev
SSLEngine on
SSLCertificateFile /path/to/MyApp/share/ssl/mysitename.crt
SSLCertificateKeyFile /path/to/MyApp/share/ssl/mysitename.key
SetEnv SLIM_MODE development
</VirtualHost>
</IfModule>
REST APIは、いくつかの重要なコンポーネントで構成されています。 1つ目は、実行する操作のタイプを定義するHTTPメソッドです。これらには、get、post、put、削除などが含まれます。 2番目のコンポーネントは、リソース識別子であるURLまたはURIです。 3番目のコンポーネントはHTTPヘッダーで、HTTPリクエストと応答のメタデータを搭載しています。 4番目のコンポーネントは本体またはペイロードで、実際のデータが送信されます。最後に、ステータスコードは、HTTP要求の成功または失敗を示します。
レストAPIを保護することは、機密データを保護するために不可欠です。認証と承認のために、APIキー、OAuth、JWTなどのさまざまな方法を使用できます。さらに、データ転送は常にデータの整合性と機密性を確保するために使用されます。脆弱性から保護するために、APIとその依存関係を定期的に更新およびパッチします。
REST APIのバージョンを使用すると、既存のクライアントに影響を与えることなく、非破壊的な変更を導入できます。 URLにバージョン番号を含めるか、カスタムリクエストヘッダーを使用してAPIをバージョンすることができます。すべての変更を記録し、API消費者に新しいバージョンとその機能を通知することを忘れないでください。
REST APIのエラーを処理する方法は?
REST APIをテストするにはどうすればよいですか?
私のREST APIを記録する方法は?
RESTFUL APIを設計する方法は?
私のREST APIで結果をページングする方法は?
私のREST APIのレートを制限する方法は?
私のREST APIを展開する方法は?