项目作者: marcanthonyconcepcion

项目描述 :
PHP Laravel REST API Web Servcie Demo
高级语言: PHP
项目地址: git://github.com/marcanthonyconcepcion/MarcPHPLaravelRESTAPIDemo.git


Marc PHP Laravel REST API Demo

PHP Laravel Installation Instructions

Get Started

  1. Install Laravel.
    1. > composer global require laravel/installer
  2. Enable ext-fileinfo in php.ini file.
    ```
    php.ini

extension=fileinfo

  1. 3. Create REST API Project.

composer create-project —prefer-dist laravel/laravel MarcSubscribersRESTAPI

  1. 4. Change directory to the name of the API project: *MarcSubscribersRESTAPI*.

cd MarcSubscribersRESTAPI

  1. 5. Edit the *.env* file to configure the database's parameters.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=subscribers_database
DB_USERNAME=user
DB_PASSWORD=password

  1. ### Create Model
  2. 6. Create the Subscriber Model Laravel object.

php artisan make:model Subscriber -m

  1. 7. Run this SQL query to create the `subscribers_database`.

MySQL script:

drop database if exists subscribers_database;
create database if not exists subscribers_database;
```

  1. Edit the MarcSubscribersRESTAPI\app\database\migrations\yyyy_mm_dd_tttttt_create_subscribers_table.php to
    configure the custom columns meant to be created on this Subscribers table.
    ```php
    <?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateSubscribersTable extends Migration
{
public function up()
{
Schema::create(‘subscribers’, function (Blueprint $table) {
$table->id();
$table->string(‘email_address’);
$table->string(‘last_name’);
$table->string(‘first_name’);
$table->boolean(‘activation_flag’)->default(0);
$table->timestamps();
});
}

  1. public function down()
  2. {
  3. Schema::dropIfExists('subscribers');
  4. }

}

  1. 9. Perform migration to create the `subscribers` database table.

php artisan migrate
```

  1. Edit the MarcSubscribersRESTAPI\app\Models\Subscribers.php.
    ```php
    <?php

namespace App\Models;

use Database\Factories\SubscriberFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Subscriber extends Model
{
use HasFactory;
protected $fillable = [‘email_address’,’last_name’,’first_name’, ‘activation_flag’];

  1. /** @return SubscriberFactory */
  2. protected static function newFactory()
  3. {
  4. return SubscriberFactory::new();
  5. }

}

  1. 11. Create the Subscribers Table Seeder.

php artisan make:seeder SubscribersTableSeeder
```

  1. Edit the MarcSubscribersRESTAPI\app\database\seeders\SubscribersTableSeeder.php
    to create the test database seeder.
    ```php
    <?php

namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Subscriber;

class SubscribersTableSeeder extends Seeder
{
public function run()
{
Subscriber::truncate();
$faker = \Faker\Factory::create();
for ($i = 0; $i < 10; $i++)
{
Subscriber::create([
‘email_address’ => $faker->email,
‘first_name’ => $faker->name,
‘last_name’ => $faker->lastName,
‘activation_flag’ => $faker->boolean,
]);
}
}
}

  1. 13. Edit also the *MarcSubscribersRESTAPI\database\seeders\DatabaseSeeder.php*
  2. for the master Database Seeder to call the custom generated Subscribers Table Seeder.
  3. ```php
  4. <?php
  5. namespace Database\Seeders;
  6. use Illuminate\Database\Seeder;
  7. class DatabaseSeeder extends Seeder
  8. {
  9. public function run()
  10. {
  11. // \App\Models\User::factory(10)->create();
  12. $this->call(SubscribersTableSeeder::class);
  13. }
  14. }
  1. Populate the subscribers database with test records.
    1. > php artisan db:seed --class=SubscribersTableSeeder

    Create Controller

  2. Create the Subscriber Controller.
    1. > php artisan make:controller SubscriberController
  3. Compose the MarcSubscribersRESTAPI\app\Http\Controllers\SubscriberController.php.
    ```php
    <?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Subscriber;

class SubscriberController extends Controller
{
public function index(): \Illuminate\Http\JsonResponse
{
if (Subscriber::all()->count() == 0)
{
return response()->json(null,204);
}
return response()->json(Subscriber::all());
}

  1. public function show(Subscriber $subscriber): \Illuminate\Http\JsonResponse
  2. {
  3. return response()->json($subscriber);
  4. }
  5. public function store(Request $request): \Illuminate\Http\JsonResponse
  6. {
  7. if($request->getQueryString() == null)
  8. {
  9. return response()->json(
  10. ["error"=> "HTTP command POST without query parameters is not allowed. Please provide an acceptable HTTP command."],
  11. 405);
  12. }
  13. return response()->json(Subscriber::create($request->all()), 201);
  14. }
  15. public function update(Request $request, Subscriber $subscriber): \Illuminate\Http\JsonResponse
  16. {
  17. if($request->getQueryString() == null)
  18. {
  19. return response()->json(
  20. ["error"=> "HTTP command PUT/PATCH without query parameters is not allowed. Please provide an acceptable HTTP command."],
  21. 405);
  22. }
  23. $subscriber->update($request->all());
  24. return response()->json($subscriber);
  25. }
  26. /**
  27. * @throws \Exception
  28. */
  29. public function delete(Subscriber $subscriber): \Illuminate\Http\JsonResponse
  30. {
  31. $subscriber->delete();
  32. return response()->json(null, 204);
  33. }

}

  1. 16. Edit the *MarcSubscribersRESTAPI\routes\api.php*.
  2. ```php
  3. <?php
  4. use Illuminate\Http\Request;
  5. use Illuminate\Support\Facades\Route;
  6. use App\Http\Controllers\SubscriberController;
  7. Route::middleware('auth:api')->get('/user', function (Request $request) {
  8. return $request->user();
  9. });
  10. Route::get('subscribers', [SubscriberController::class,'index']);
  11. Route::get('subscribers/{subscriber}', [SubscriberController::class,'show']);
  12. Route::post('subscribers', [SubscriberController::class,'store']);
  13. Route::put('subscribers/{subscriber}', [SubscriberController::class,'update']);
  14. Route::patch('subscribers/{subscriber}', [SubscriberController::class,'update']);;
  15. Route::delete('subscribers/{subscriber}', [SubscriberController::class,'delete']);
  16. Route::fallback(function () {
  17. return response()->json(['error' => 'Invalid URL syntax. Please provide acceptable HTTP URL.'], 400);
  18. });
  1. Edit the MarcSubscribersRESTAPI\app\Exceptions\Handler.php
    to accommodate HTTP error code handling and exception/error handling.
    ```php
    <?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Symfony\Component\HttpKernel\Exception\HttpException;

class Handler extends ExceptionHandler
{
protected $dontReport = [
//
];

  1. protected $dontFlash = [
  2. 'current_password',
  3. 'password',
  4. 'password_confirmation',
  5. ];
  6. public function register()
  7. {
  8. $this->reportable(function (Throwable $e) {
  9. return response()->json(['error' => $e->getMessage()], 500);
  10. });
  11. $this->renderable(function (HttpException $e) {
  12. if ($e->getStatusCode() == 404)
  13. {
  14. return response()->json(['error' => 'The records or resources that you requested are not available.'],
  15. 404);
  16. }
  17. return response()->json(['error' => $e->getMessage()], $e->getStatusCode());
  18. });
  19. $this->renderable(function (Throwable $e) {
  20. return response()->json(
  21. ['error' => 'Error caused by server or client. Please provide acceptable API Command'],500);
  22. });
  23. }

}

  1. ### Create PHP Unit Tests
  2. 18. Set the **DB_CONNECTION** to *mysql* *MarcSubscribersRESTAPI\phpunit.xml*.
  3. ```xml
  4. <php>
  5. <server name="DB_CONNECTION" value="mysql"></server>
  6. </php>
  1. Edit MarcSubscribersRESTAPI\tests\TestCase.php to incorporate database test seeding.
    ```php
    <?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Support\Facades\Artisan;

abstract class TestCase extends BaseTestCase
{
use CreatesApplication, DatabaseMigrations;

  1. function setUp() : void
  2. {
  3. parent::setUp();
  4. Artisan::call('db:seed');
  5. }

}

  1. 20. Compose the *MarcSubscribersRESTAPI\database\factories\SubscriberFactory.php*
  2. to create a Subscriber database factory.
  3. ```php
  4. <?php
  5. namespace Database\Factories;
  6. use App\Models\Subscriber;
  7. use Illuminate\Database\Eloquent\Factories\Factory;
  8. use JetBrains\PhpStorm\ArrayShape;
  9. class SubscriberFactory extends Factory
  10. {
  11. protected string $model = Subscriber::class;
  12. #[ArrayShape(['email_address' => "string", 'first_name' => "string", 'last_name' => "string", 'activation_flag' => "bool"])]
  13. public function definition()
  14. {
  15. return [
  16. 'email_address' => $this->faker->email,
  17. 'first_name' => $this->faker->name,
  18. 'last_name' => $this->faker->lastName,
  19. 'activation_flag' => $this->faker->boolean,
  20. ];
  21. }
  22. }
  1. Create the Subscriber Test PHPUnit test template.
    1. > php artisan make:test SubscriberTest
  2. Compose the MarcSubscribersRESTAPI\tests\Feature\SubscriberTest.php
    to create the Subscriber Test PHP Unit Feature Test Cases.
    ```php
    <?php

namespace Tests\Feature;
use Tests\TestCase;
use App\Models\Subscriber;

class SubscriberTest extends TestCase
{
public function testPost()
{
$payload = [ ‘email_address’ => ‘riseofskywalker@starwars.com’,
‘first_name’ => ‘Rey’,
‘last_name’ => ‘Palpatine’,
‘activation_flag’ => false ];
$this->json(‘POST’, ‘/api/subscribers?email_address=’.$payload[‘email_address’].
‘&last_name=’.$payload[‘last_name’].
‘&first_name=’.$payload[‘first_name’], $payload)
->assertStatus(201)
->assertJson([ ‘email_address’ => ‘riseofskywalker@starwars.com’,
‘first_name’ => ‘Rey’,
‘last_name’ => ‘Palpatine’,
‘activation_flag’ => false ]);
}

  1. public function testGet()
  2. {
  3. $subscriber = Subscriber::factory(Subscriber::class)->create([
  4. 'email_address' => 'riseofskywalker@starwars.com',
  5. 'first_name' => 'Rey',
  6. 'last_name' => 'Palpatine',
  7. 'activation_flag' => false
  8. ]);
  9. $this->json('GET', '/api/subscribers/'.$subscriber->id.'/')->assertStatus(200);
  10. }
  11. public function testGetAll()
  12. {
  13. Subscriber::factory(Subscriber::class)->create([
  14. 'email_address' => 'riseofskywalker@starwars.com',
  15. 'first_name' => 'Rey',
  16. 'last_name' => 'Palpatine',
  17. 'activation_flag' => false
  18. ]);
  19. $this->json('GET', '/api/subscribers')->assertStatus(200);
  20. }
  21. public function testPut()
  22. {
  23. $subscriber = Subscriber::factory(Subscriber::class)->create([
  24. 'email_address' => 'riseofskywalker@starwars.com',
  25. 'first_name' => 'Rey',
  26. 'last_name' => 'Palpatine',
  27. 'activation_flag' => false
  28. ]);
  29. $payload = ['last_name' => 'Skywalker'];
  30. $this->json('PUT', '/api/subscribers/'.$subscriber->id.'?last_name='.$payload['last_name'], $payload)
  31. ->assertStatus(200)
  32. ->assertJson([ 'email_address' => 'riseofskywalker@starwars.com',
  33. 'first_name' => 'Rey',
  34. 'last_name' => 'Skywalker',
  35. 'activation_flag' => false ]);
  36. }
  37. public function testPatch()
  38. {
  39. $subscriber = Subscriber::factory(Subscriber::class)->create([
  40. 'email_address' => 'riseofskywalker@starwars.com',
  41. 'first_name' => 'Rey',
  42. 'last_name' => 'Palpatine',
  43. 'activation_flag' => false
  44. ]);
  45. $payload = ['last_name' => 'Skywalker'];
  46. $this->json('PATCH', '/api/subscribers/'.$subscriber->id.'?last_name='.$payload['last_name'], $payload)
  47. ->assertStatus(200)
  48. ->assertJson([ 'email_address' => 'riseofskywalker@starwars.com',
  49. 'first_name' => 'Rey',
  50. 'last_name' => 'Skywalker',
  51. 'activation_flag' => false ]);
  52. }
  53. public function testDelete()
  54. {
  55. $subscriber = Subscriber::factory(Subscriber::class)->create([
  56. 'email_address' => 'riseofskywalker@starwars.com',
  57. 'first_name' => 'Rey',
  58. 'last_name' => 'Palpatine',
  59. 'activation_flag' => false
  60. ]);
  61. $this->json('DELETE', '/api/subscribers/'.$subscriber->id)->assertStatus(204);
  62. }
  63. public function testGetNonExistentRecord()
  64. {
  65. $this->json('GET', '/api/subscribers/4000/')->assertStatus(404);
  66. }
  67. public function testGetNonExistentResource()
  68. {
  69. $this->json('GET', '/api/notsubscribers/')->assertStatus(400);
  70. }
  71. public function testGetNonAPICall()
  72. {
  73. $this->json('GET', '/nonapi')->assertStatus(404);
  74. }
  75. public function testNonCRUDMethod()
  76. {
  77. $this->json('TRACE', '/api/subscribers/')->assertStatus(405);
  78. $this->json('PATCH', '/api/subscribers/')->assertStatus(405);
  79. }
  80. public function testPostWithID()
  81. {
  82. $payload = [
  83. 'email_address' => 'riseofskywalker@starwars.com',
  84. 'first_name' => 'Rey',
  85. 'last_name' => 'Palpatine',
  86. 'activation_flag' => false
  87. ];
  88. $this->json('POST', '/api/subscribers/1', $payload)->assertStatus(405);
  89. }
  90. public function testPostWithoutPayload()
  91. {
  92. $this->json('POST', '/api/subscribers/')->assertStatus(405);
  93. }
  94. public function testPutWithoutID()
  95. {
  96. $payload = [
  97. 'email_address' => 'riseofskywalker@starwars.com',
  98. 'first_name' => 'Rey',
  99. 'last_name' => 'Palpatine',
  100. 'activation_flag' => false
  101. ];
  102. $this->json('PUT', '/api/subscribers/', $payload)->assertStatus(405);
  103. }
  104. public function testPatchWithoutID()
  105. {
  106. $payload = [
  107. 'email_address' => 'riseofskywalker@starwars.com',
  108. 'first_name' => 'Rey',
  109. 'last_name' => 'Palpatine',
  110. 'activation_flag' => false
  111. ];
  112. $this->json('PATCH', '/api/subscribers/', $payload)->assertStatus(405);
  113. }
  114. public function testPutWithoutPayload()
  115. {
  116. $subscriber = Subscriber::factory(Subscriber::class)->create([
  117. 'email_address' => 'riseofskywalker@starwars.com',
  118. 'first_name' => 'Rey',
  119. 'last_name' => 'Palpatine',
  120. 'activation_flag' => false
  121. ]);
  122. $this->json('PUT', '/api/subscribers/'.$subscriber->id)->assertStatus(405);
  123. }
  124. public function testPatchWithoutPayload()
  125. {
  126. $subscriber = Subscriber::factory(Subscriber::class)->create([
  127. 'email_address' => 'riseofskywalker@starwars.com',
  128. 'first_name' => 'Rey',
  129. 'last_name' => 'Palpatine',
  130. 'activation_flag' => false
  131. ]);
  132. $this->json('PATCH', '/api/subscribers/'.$subscriber->id)->assertStatus(405);
  133. }
  134. public function testDeleteWithoutID()
  135. {
  136. $this->json('DELETE', '/api/subscribers/')->assertStatus(405);
  137. }

}

  1. 23. Test if the PHP Unit tests would return good test results.

php artisan test
Warning: TTY mode is not supported on Windows platform.

PASS Tests\Unit\ExampleTest
✓ basic test

PASS Tests\Feature\ExampleTest
✓ basic test

PASS Tests\Feature\SubscriberTest
✓ post
✓ get
✓ get all
✓ put
✓ patch
✓ delete
✓ get non existent record
✓ get non existent resource
✓ get non a p i call
✓ non c r u d method
✓ post with i d
✓ post without payload
✓ put without i d
✓ patch without i d
✓ put without payload
✓ patch without payload
✓ delete without i d

Tests: 19 passed
Time: 7.18s

  1. ### Set up the System Test
  2. 24. Test launch the Laravel development server via Artisan Console. Press CTRL-C to terminate.

php artisan serve
Starting Laravel development server: http://127.0.0.1:8000
[Thu Apr 1 11:11:11 2021] PHP 8.0.1 Development Server (http://127.0.0.1:8000) started

  1. 25. Perform migration again to refresh the state of the `subscriber` table in the MySQL `subscriber_database`.

php artisan migrate

  1. 26. Populate the new `subscribers` table with test records if you want to.

php artisan db:seed —class=SubscribersTableSeeder
```

  1. Use HTTPie as a good HTTP client console.
  1. Perform System Test as stipulated on the next section below:

FUNCTIONAL TEST SAMPLES

Requirement 1: Create a new subscriber user record

Demonstrates POST without ID and CREATE a specified single record

  1. > http post http://127.0.0.1:8000/api/subscribers?email_address=riseofskywalker@starwars.com"&"last_name=Palpatine"&"first_name=Rey
  2. HTTP/1.1 201 Created
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 59
  11. {
  12. "created_at": "2021-04-10T14:00:59.000000Z",
  13. "email_address": "riseofskywalker@starwars.com",
  14. "first_name": "Rey",
  15. "id": 11,
  16. "last_name": "Palpatine",
  17. "updated_at": "2021-04-10T14:00:59.000000Z"
  18. }

Requirement 2-1: Fetch a subscriber user record

Demonstrates GET with ID and RETRIEVE a specified single record

  1. > http get http://127.0.0.1:8000/api/subscribers/11
  2. HTTP/1.1 200 OK
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 58
  11. {
  12. "activation_flag": 0,
  13. "created_at": "2021-04-10T14:00:59.000000Z",
  14. "email_address": "riseofskywalker@starwars.com",
  15. "first_name": "Rey",
  16. "id": 11,
  17. "last_name": "Palpatine",
  18. "updated_at": "2021-04-10T14:00:59.000000Z"
  19. }

Requirement 2-2: Fetch all subscriber user records

Demonstrates GET without ID and RETRIEVE all single records

  1. > http get http://127.0.0.1:8000/api/subscribers
  2. HTTP/1.1 200 OK
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 59
  11. [
  12. {
  13. "activation_flag": 1,
  14. "created_at": "2021-04-10T14:00:46.000000Z",
  15. "email_address": "dwisozk@marquardt.com",
  16. "first_name": "Ally Purdy",
  17. "id": 1,
  18. "last_name": "Koelpin",
  19. "updated_at": "2021-04-10T14:00:46.000000Z"
  20. },
  21. {
  22. "activation_flag": 1,
  23. "created_at": "2021-04-10T14:00:46.000000Z",
  24. "email_address": "zwisoky@gmail.com",
  25. "first_name": "Antonietta Bauch",
  26. "id": 2,
  27. "last_name": "Wuckert",
  28. "updated_at": "2021-04-10T14:00:46.000000Z"
  29. },
  30. {
  31. "activation_flag": 1,
  32. "created_at": "2021-04-10T14:00:46.000000Z",
  33. "email_address": "lockman.ewell@yahoo.com",
  34. "first_name": "Mrs. Caterina Trantow",
  35. "id": 3,
  36. "last_name": "Abshire",
  37. "updated_at": "2021-04-10T14:00:46.000000Z"
  38. },
  39. {
  40. "activation_flag": 1,
  41. "created_at": "2021-04-10T14:00:46.000000Z",
  42. "email_address": "qfeeney@yahoo.com",
  43. "first_name": "Dr. Theron McLaughlin",
  44. "id": 4,
  45. "last_name": "Schaden",
  46. "updated_at": "2021-04-10T14:00:46.000000Z"
  47. },
  48. {
  49. "activation_flag": 1,
  50. "created_at": "2021-04-10T14:00:46.000000Z",
  51. "email_address": "uturcotte@yahoo.com",
  52. "first_name": "Verona Swift",
  53. "id": 5,
  54. "last_name": "Batz",
  55. "updated_at": "2021-04-10T14:00:46.000000Z"
  56. },
  57. {
  58. "activation_flag": 0,
  59. "created_at": "2021-04-10T14:00:46.000000Z",
  60. "email_address": "may.parisian@hotmail.com",
  61. "first_name": "Neva Cruickshank",
  62. "id": 6,
  63. "last_name": "Kilback",
  64. "updated_at": "2021-04-10T14:00:46.000000Z"
  65. },
  66. {
  67. "activation_flag": 0,
  68. "created_at": "2021-04-10T14:00:46.000000Z",
  69. "email_address": "feeney.golden@gmail.com",
  70. "first_name": "Montana Graham I",
  71. "id": 7,
  72. "last_name": "Jaskolski",
  73. "updated_at": "2021-04-10T14:00:46.000000Z"
  74. },
  75. {
  76. "activation_flag": 0,
  77. "created_at": "2021-04-10T14:00:46.000000Z",
  78. "email_address": "mervin30@yahoo.com",
  79. "first_name": "Florian Bergstrom",
  80. "id": 8,
  81. "last_name": "Prohaska",
  82. "updated_at": "2021-04-10T14:00:46.000000Z"
  83. },
  84. {
  85. "activation_flag": 1,
  86. "created_at": "2021-04-10T14:00:46.000000Z",
  87. "email_address": "leonora.stehr@yahoo.com",
  88. "first_name": "Mike Reilly",
  89. "id": 9,
  90. "last_name": "Maggio",
  91. "updated_at": "2021-04-10T14:00:46.000000Z"
  92. },
  93. {
  94. "activation_flag": 0,
  95. "created_at": "2021-04-10T14:00:46.000000Z",
  96. "email_address": "phyllis.spencer@yahoo.com",
  97. "first_name": "Ms. Kiera Huels",
  98. "id": 10,
  99. "last_name": "Marquardt",
  100. "updated_at": "2021-04-10T14:00:46.000000Z"
  101. },
  102. {
  103. "activation_flag": 0,
  104. "created_at": "2021-04-10T14:00:59.000000Z",
  105. "email_address": "riseofskywalker@starwars.com",
  106. "first_name": "Rey",
  107. "id": 11,
  108. "last_name": "Palpatine",
  109. "updated_at": "2021-04-10T14:00:59.000000Z"
  110. }
  111. ]

If there are no records in the database, the API shall return an HTTP 204: No Content status code.

  1. > http get http://127.0.0.1:8000/api/subscribers
  2. HTTP/1.1 204 No Content
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Host: 127.0.0.1:8000
  7. X-Powered-By: PHP/8.0.1
  8. X-RateLimit-Limit: 60
  9. X-RateLimit-Remaining: 59

Requirement 3-1: Edit an existing subscriber user record

Demonstrates PUT with ID and UPDATE a specified single record

  1. > http put http://127.0.0.1:8000/api/subscribers/11?last_name=Skywalker
  2. HTTP/1.1 200 OK
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 59
  11. {
  12. "activation_flag": 0,
  13. "created_at": "2021-04-10T14:00:59.000000Z",
  14. "email_address": "riseofskywalker@starwars.com",
  15. "first_name": "Rey",
  16. "id": 11,
  17. "last_name": "Skywalker",
  18. "updated_at": "2021-04-10T14:04:03.000000Z"
  19. }

Requirement 3-2: Edit an existing subscriber user record

Demonstrates PATCH with ID and UPDATE a specified single record

  1. > http patch http://127.0.0.1:8000/api/subscribers/1?activation_flag=1
  2. HTTP/1.1 200 OK
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 59
  11. {
  12. "activation_flag": "1",
  13. "created_at": "2021-04-10T15:01:52.000000Z",
  14. "email_address": "riseofskywalker@starwars.com",
  15. "first_name": "Rey",
  16. "id": 1,
  17. "last_name": "Palpatine",
  18. "updated_at": "2021-04-10T15:04:39.000000Z"
  19. }

Requirement 4: Delete an existing subscriber user record

Demonstrates DELETE with ID and DELETE a specified single record

  1. > http delete http://127.0.0.1:8000/api/subscribers/11
  2. HTTP/1.1 204 No Content
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Host: 127.0.0.1:8000
  7. X-Powered-By: PHP/8.0.1
  8. X-RateLimit-Limit: 60
  9. X-RateLimit-Remaining: 58

Error Test Case 1: Get a record of a subscriber who does not exist.

  1. > http get http://127.0.0.1:8000/api/subscribers/400
  2. HTTP/1.1 404 Not Found
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 58
  11. {
  12. "error": "The records or resources that you requested are not available."
  13. }

Error Test Case 2: Call an API without the prescribed ‘subscribers’ model

  1. > http get http://127.0.0.1:8000/api/
  2. HTTP/1.0 404 Not Found
  3. Cache-Control: no-cache, private
  4. Connection: close
  5. Content-Type: application/json
  6. Host: 127.0.0.1:8000
  7. X-Powered-By: PHP/8.0.1
  8. {
  9. "error": "The records or resources that you requested are not available. "
  10. }

Error Test Case 3: Call an API with a model that is not ‘subscribers’

  1. > http get http://127.0.0.1:8000/api/notsubscribers/11
  2. HTTP/1.1 400 Bad Request
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 59
  11. {
  12. "error": "Invalid URL syntax. Please provide acceptable HTTP URL."
  13. }

Error Test Case 4: Call HTTP commands that are not being used by the API.

  1. > http trace http://127.0.0.1:8000/api/subscribers/
  2. HTTP/1.0 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. {
  10. "error": "The TRACE method is not supported for this route. Supported methods: GET, HEAD, PUT, PATCH, DELETE."
  11. }

Error Test Case 5-1: POST with specified ID.

  1. > http post http://127.0.0.1:8000/api/subscribers/12?email_address=riseofskywalker@starwars.com"&"last_name=Palpatine"&"first_name=Rey
  2. HTTP/1.0 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. {
  10. "error": "The POST method is not supported for this route. Supported methods: GET, HEAD, PUT, PATCH, DELETE."
  11. }

Error Test Case 5-2: POST without required parameters

  1. > http post http://127.0.0.1:8000/api/subscribers/
  2. HTTP/1.1 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 58
  11. {
  12. "error": "HTTP command POST without query parameters is not allowed. Please provide an acceptable HTTP command."
  13. }

Error Test Case 5-3: PUT without specified ID.

  1. > http put http://127.0.0.1:8000/api/subscribers?last_name=Skywalker
  2. HTTP/1.0 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. {
  10. "error": "The PUT method is not supported for this route. Supported methods: GET, HEAD, POST."
  11. }

Error Test Case 5-4: PATCH without specified ID.

  1. > http patch http://127.0.0.1:8000/api/subscribers/?activation_flag=1
  2. HTTP/1.0 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. {
  10. "error": "The PATCH method is not supported for this route. Supported methods: GET, HEAD, POST."
  11. }

Error Test Case 5-5: PUT without required parameters

  1. > http put http://127.0.0.1:8000/api/subscribers/1
  2. HTTP/1.1 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 57
  11. {
  12. "error": "HTTP command PUT/PATCH without query parameters is not allowed. Please provide an acceptable HTTP command."
  13. }

Error Test Case 5-6: PATCH without required parameters

  1. > http patch http://127.0.0.1:8000/api/subscribers/1
  2. HTTP/1.1 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. X-RateLimit-Limit: 60
  10. X-RateLimit-Remaining: 59
  11. {
  12. "error": "HTTP command PUT/PATCH without query parameters is not allowed. Please provide an acceptable HTTP command."
  13. }

Error Test Case 5-7: DELETE without specified ID

  1. > http delete http://127.0.0.1:8000/api/subscribers/
  2. HTTP/1.0 405 Method Not Allowed
  3. Access-Control-Allow-Origin: *
  4. Cache-Control: no-cache, private
  5. Connection: close
  6. Content-Type: application/json
  7. Host: 127.0.0.1:8000
  8. X-Powered-By: PHP/8.0.1
  9. {
  10. "error": "The DELETE method is not supported for this route. Supported methods: GET, HEAD, POST."
  11. }

Error Test Case 6: API Request to other unrecognized API resources

  1. > http get http://127.0.0.1:8000/notapi
  2. HTTP/1.0 404 Not Found
  3. Cache-Control: no-cache, private
  4. Connection: close
  5. Content-Type: application/json
  6. Host: 127.0.0.1:8000
  7. X-Powered-By: PHP/8.0.1
  8. {
  9. "error": "The records or resources that you requested is not available. "
  10. }

For more inquiries, please feel free to e-mail me at marcanthonyconcepcion@gmail.com.

Thank you.

:copyright: 2021 Marc Concepcion

END