Laravel Fluent Part Two: The Public API

November 21, 2016 —John Koster

This article is part of a two part series covering the Laravel Fluent API. The articles in this series are:

The following sections will highlight the usage of the various public methods that the Fluent class provides. There are, however, some omissions in this section, namely the methods required to implement PHP's ArrayAccess interface. The examples that follow will assume the following test array and object, unless stated otherwise:

1<?php
2 
3// A test array for use with Fluent.
4$testArray = [
5 'first' => 'The first value',
6 'second' => 'The second value',
7 'third' => 'The third value'
8];
9 
10// A test object for use with Fluent.
11$testObject = new stdClass;
12$testObject->first = 'The first value';
13$testObject->second = 'The second value';
14$testObject->third = 'The third value';

#get($key, $default = null)

The get method will return the value associated with the provided $key. If the $key does not exist, the $default value will be returned (which is null by default).

Retrieving values from a Fluent instance:

1<?php
2 
3$fluent = new Fluent($testArray);
4 
5// The first value
6$message = $fluent->get('first');
7 
8$fluent = new Fluent($testObject);
9 
10// The first value
11$message = $fluent->get('first');
12 
13// null
14$willBeNull = $fluent->get('does_not_exist');

The $default value is evaluated using the value helper function, meaning that it can be the result of a function:

1<?php
2 
3$fluent = new Fluent($testArray);
4 
5// Does not exist yet!
6$message = $fluent->get('does_not_exist', function() {
7 return 'Does not exist yet!';
8});

#Fluent and Closures

If we look at the following code example, one might be tempted to say that the value of $message would be Hello, world!, but that would be incorrect:

1<?php
2 
3$testObject = new stdClass;
4$testObject->method = function() {
5 return 'Hello, world!';
6};
7 
8$fluent = new Fluent($testObject);
9 
10$message = $fluent->method;
11 
12// Or even this:
13 
14$message = $fluent->get('method');

However, that would be incorrect. It is important to remember that the Fluent object is an elaborate key/value storage container that can behave like an array or an object. When the fluent container is created for an object containing a closure, such as the above example, the closure instance is stored as the value. The following code will quickly prove this:

1<?php
2 
3// true
4$isClosure = ($fluent->method instanceof Closure):

To evaluate the closure and get the results, the value helper function can be used:

1<?php
2 
3// Hello, world!
4$message = value($fluent->method);
5 
6// Hello, world!
7$message = value($fluent->get('method'));

#getAttributes()

The getAttributes method simply returns an array containing all key/value pairs, representing the underlying data contained within the Fluent instance.

After the following code is executed:

1<?php
2 
3$fluent = new Fluent($testObject);
4 
5$attributes = $fluent->getAttributes();

The $attributes variable would look have a value similar to the following:

1array (size=4)
2 'first' => string 'The first value' (length=15)
3 'second' => string 'The second value' (length=16)
4 'third' => string 'The third value' (length=15)

#toArray()

The toArray method returns the exact same values as the getAttributes method.

#jsonSerialize()

The jsonSerialize method internally returns a call to toArray. Because of this, toArray, jsonSerialize and getAttributes are all functionally equivalent. The jsonSerialize method exists to satisfy PHP's JsonSerializable interface, which allows developers to customize how a class is represented when using the json_encode function.

#toJson($options = 0)

The toJson method will return a JSON encoded version of the data stored within the fluent instance. It internally does this by returning a call to PHP's json_encode function, passing in any $options that were supplied. Like the json_encode function, the $options parameter is a bitmask of the predefined JSON constants.

The following code:

1<?php
2 
3$fluent = new Fluent($testObject);
4 
5$jsonValue = $fluent->toJson();

would be converted into the following JSON, stored in the $jsonValue variable:

1{"first":"The first value","second":"The second value","third":
2 "The third value","method":{}}

Alternatively, a well-formatted value can be returned by passing in the JSON_PRETTY_PRINT constant:

1<?php
2 
3$fluent = new Fluent($testObject);
4 
5$jsonValue = $fluent->toJson(JSON_PRETTY_PRINT);

This time, the $jsonValue would contain the following value:

1{
2 "first": "The first value",
3 "second": "The second value",
4 "third": "The third value",
5 "method": {}
6}

#toJson and Deeply Nested Data Structures

The toJson method internally makes a call to PHP's json_encode function. Unlike json_encode, toJson does not provide a way to specify the depth (essentially how many arrays are nested inside of each other) to which data will be encoded, which is by default set to 512. To convert a fluent object into its JSON equivalent with a depth greater than 512, the following method will be sufficient:

1<?php
2 
3$fluent = new Fluent($testObject);
4 
5// Replace 512 with the desired depth.
6$jsonValue = json_encode($fluent->jsonSerialize(), 0, 512);

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.