# Links

# Introduction

A resource object may have a links object (opens new window) containing links related to the resource. By default we include the self link for each resource that is recommended by the JSON:API specification. However you are also able to provide other non-standard links if required.

In JSON:API links can either be strings, or a JSON object containing a href member (the string URI) and a meta member. The meta object would contain non-standard meta-information about the link.

By default each resource object will contain a self link. This is the URL at which the resource can be read, updated and deleted. Its inclusion is recommended by the JSON:API specification.

The URL for this link is generated by appending the resource type and id to the Server's URI namespace. As the URL is generated using Laravel's url helper (opens new window), the hostname will also be included.

For example, if our server has a namespace of /api/v1, the posts resource with an id of 123 will have have a links member:

{
  "type": "posts",
  "id": "123",
  "attributes": {
    "content": "...",
    "createdAt": "2020-07-10T12:42:17.000000Z",
    "title": "Hello World!",
    "updatedAt": "2020-07-10T13:53:01.000000Z"
  },
  "links": {
    "self": "http://localhost/api/v1/posts/123"
  }
}

TIP

The self link returned by the resource object is also used when generating relationship links.

# Customising the URL

If you need different logic for the self link, implement the selfUrl method on your resource:

/**
 * Get the resource's `self` link URL.
 *
 * @return string
 */
public function selfUrl(): string
{
    if ($this->selfUri) {
        return $this->selfUri;
    }

    return $this->selfUri = url('/foo/bar/posts', $this->id());
}

Note that we cache the calculated value so that it only has to be calculated once.

# Adding Meta

If you would like to add meta to the self link, implement the selfMeta method:

/**
 * Get meta for the `self` link.
 *
 * @return array
 */
protected function selfMeta(): array
{
    return [
      'foo' => 'bar',
      'baz' => 'bat',
    ];
}

For example, this would result in the following posts resource object:

{
  "type": "posts",
  "id": "123",
  "attributes": {
    "content": "...",
    "createdAt": "2020-07-10T12:42:17.000000Z",
    "title": "Hello World!",
    "updatedAt": "2020-07-10T13:53:01.000000Z"
  },
  "links": {
    "self": {
      "href": "http://localhost/api/v1/posts/123",
      "meta": {
        "foo": "bar",
        "baz": "bat"
      }
    }
  }
}

The JSON:API specification is unclear as to whether other non-standard links are allowed on a resource object. The implication is only defined links members are allowed, and that more members may be specified in the future.

This means we would generally discourage adding non-standard links to your resource objects. However, if you do need to add non-standard links, implement the links method on your resource:

use LaravelJsonApi\Core\Document\Link;
use LaravelJsonApi\Core\Document\Links;

/**
 * Get the resource's links.
 *
 * @param \Illuminate\Http\Request|null $request
 * @return Links
 */
public function links($request): Links
{
    return new Links(
      $this->selfLink(),

      new Link(
        'download',
        url('/api/v1/posts', [$this->id(), 'download']),
        ['foo' => 'bar']
      ),
    );
}

As you can see, we return a Links object. Each argument provided to the constructor is a Link object. Note that we call $this->selfLink() to ensure the self link is included.

When creating a Link object, you must provide two arguments: the member name of the link, and the URL. An optional third member allows meta to be added.

Our example above would generate the following posts resource:

{
  "type": "posts",
  "id": "123",
  "attributes": {
    "content": "...",
    "createdAt": "2020-07-10T12:42:17.000000Z",
    "title": "Hello World!",
    "updatedAt": "2020-07-10T13:53:01.000000Z"
  },
  "links": {
    "self": "http://localhost/api/v1/posts/123",
    "download": {
      "href": "http://localhost/api/v1/posts/123/download",
      "meta": {
        "foo": "bar"
      }
    }
  }
}
Last Updated: 1/31/2021, 3:52:09 PM