Skip to content

3.3: Example: Listing Users

Sebastian Schendel edited this page Jun 17, 2023 · 5 revisions

Let us get to a real-world example of an endpoint that enables an authenticated user to get a list of all users.

At first we need to define the routes in the file /site/api/Routes.php (or a custom file if you changed it in the module's settings):

<?php
namespace ProcessWire;

// These two lines are necessary to make shure that everyting is loaded correctly:
require_once wire('config')->paths->AppApi . "vendor/autoload.php";
require_once wire('config')->paths->AppApi . "classes/AppApiHelper.php";

// After that, you define your classes that are called by the routes:
require_once __DIR__ . "/Example.php";

// The $routes-array will be imported by the module:
$routes = [
  'users' => [
    ['OPTIONS', '', ['GET']], // this is needed for CORS Requests
    ['GET', '', Example::class, 'getAllUsers', ["auth" => true]],
    ['OPTIONS', '{id:\d+}', ['GET']], // this is needed for CORS Requests
    ['GET', '{id:\d+}', Example::class, 'getUser', ["auth" => true]]
  ],
];

We defined two GET-endpoints, that are only available for logged-in users. If not logged-in, the module will throw an exception:

throw new AppApiException('User does not have authorization', 401);

As you see, we don't have to bother much about authentication. Our routes are protected against unauthorized access. But keep in mind: You can throw a custom Exception at any point in your functions as well.

So, our next step is to define the Example-class which functions are called from our router:

<?php
namespace ProcessWire;

class Example {
  /**
   * Returns a list of all users that are available
   */
  public static function getAllUsers() {
    // In our $response-array we collect everythin that should be returned:
    $response = [
      'users' => []
    ];

    // Collect id and username of every user and put it to the users-array:
    foreach(wire('users') as $user) {
      array_push($response['users'], [
        "id" => $user->id,
        "name" => $user->name
      ]);
    }

    return $response;
  }

  /**
   * Return username and id of one individual user
   */
  public static function getUser($data) {
    // $data will contain all GET-params, that were included in the request.
    // For POST-requests it would contain the response-body vars.

    // Use this helper-function to check and validate a parameter in one line.
    // An exception will be thrown, if $data['id'] does not exist
    $data = AppApiHelper::checkAndSanitizeRequiredParameters($data, ['id|int']);

    // We collect our response-data in an empty StdClass. json_encode can handle StdClasses
    // as well, so its no problem.
    $response = new \StdClass();
    $user = wire('users')->get($data->id);

    // If the user does not exist, we throw a 404 exception and escape.
    if(!$user->id) throw new \Exception('User not found', 404);

    $response->id = $user->id;
    $response->name = $user->name;

    return $response;
  }
}

The response of our /api/users/-call will be something like that:

{
  "users": [
    { "id": 41, "name": "admin" },
    { "id": 42, "name": "test-user" },
    { "id": 123, "name": "anotheruser" }
  ]
}

The second call to, let's say /api/users/42, will output the following JSON:

{
  "id": 42,
  "name": "test-user"
}

➡️ Continue with 3.4: Add Documentation ⬅️ Back to 3.2: Error Handling