Optional arguments kwargs in PHP
Goal
Create a function that reads a JSON file and returns its content as an array or object.
There are many optional arguments in json_decode()
and file_get_contents()
native PHP functions.
These args are all lined up within the argument parentheses.
I don't want to line them up in my new function, that's insane.
I want to create keyword arguments for a PHP function, just like I could do in Ruby or Python.
Ruby and Python kwargs
Ruby and Python have kwargs: named arguments passed in a function/method grouped as a hash or dictionary.
Ruby kwargs
In Ruby, the named arguments are hash items and result in a hash.
def print_kwargs(**kwargs)
puts kwargs.inspect
end
print_kwargs(make: "Honda", model: "Civic", year: "1991")
print_kwargs(:make=>"Honda", :model=>"Civic", :year=>"1991")
# Curly brackets are optional
print_kwargs({make: "Honda", model: "Civic", year: "1991"})
kwargs = {:make=>"Honda", :model=>"Civic", :year=>"1991"}
print_kwargs(kwargs)
Result:
{:make=>"Honda", :model=>"Civic", :year=>"1991"}
Python kwargs
In Python, the named arguments result in a dictionary.
def print_kwargs(**kwargs):
print(kwargs)
print_kwargs(make="Honda", model="Civic", year="1991")
Result:
{'make': 'Honda', 'model': 'Civic', 'year': '1991'}
PHP kwargs
In PHP, I can feed a function some associative array to act as kwargs.
function print_kwargs(array $kwargs = []) {
var_export($kwargs);
}
print_kwargs(['make'=>"Honda", 'model'=>"Civic", 'year'=>"1991"]);
Result:
array (
'make' => 'Honda',
'model' => 'Civic',
'year' => '1991',
)
Create a PHP function with kwargs
- Create function with kwargs.
- Override default options with provided kwargs.
- Use kwargs keys as local variables for clarity.
Needed native PHP functions
Look at the optional arguments of native PHP functions I want to use.
file_get_contents()
https://www.php.net/manual/en/function.file-get-contents.php
file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] ) : string
json_decode()
https://www.php.net/manual/en/function.json-decode.php
json_decode ( string $json [, bool $assoc = FALSE [, int $depth = 512 [, int $options = 0 ]]] ) : mixed
My function
/**
* Read a json file and returns its content as an array or object.
*
* @params string $filename
* @params array $kwargs
* @return mixed
*/
function json_read($filename, array $kwargs = []) {
extract($kwargs + [
'assoc' => TRUE, // TRUE= associative array, FALSE= stdClass object
'depth' => 512,
'options' => 0,
'use_include_path' => FALSE,
]);
$json = @file_get_contents($filename, $use_include_path);
return json_decode($json, $assoc, $depth, $options);
}
Explanation
Using native PHP function argument variable names as kwargs
I usually use the same function argument variable names when I call a native PHP function.
file_get_contents()
For file_get_contents()
, I don't need all the optional arguments listed in its definition.
file_get_contents($filename, $use_include_path, $context, $offset, $maxlen);
I just need file_get_contents($filename, $use_include_path)
.
json_decode()
For json_decode()
, I need all the optional arguments listed in its definition.
json_decode($json, $assoc, $depth, $options);
In fact, I want to return the result of the json_decode()
call.
json_read()
is like json_decode()
but reading a file as a string to feed json_decode()
.
Declaring default options
I use native PHP function argument variable names ('assoc', 'depth', 'options', 'use_include_path') as kwargs keys and values.
I am modifying the default option $assoc = FALSE
to TRUE
in my json_decode()
call.
extract($kwargs + [
'assoc' => TRUE, // TRUE= associative array, FALSE= stdClass object
'depth' => 512,
'options' => 0,
'use_include_path' => FALSE,
]);
Overriding default options
I am using the Union of two arrays to override the default options.
"The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored."
So:
['options'=>JSON_BIGINT_AS_STRING] + ['options'=>0] // => ['options'=>2] because JSON_BIGINT_AS_STRING = (integer) 2
So in this function call:
json_read($filename, ['options'=>JSON_BIGINT_AS_STRING]);
I merge $kwargs
and defaults with the Union
of the provided $kwargs
plus the default $kwargs
that contains default options.
$kwargs + ['options'=>0] // => ['options'=>2]
So the default option ['options'=>0]
gets overridden by the provided kwarg ['options'=>JSON_BIGINT_AS_STRING]
.
Extracting to local variables
Instead of this:
return json_decode($json, $kwargs['assoc'], $kwargs['depth'], $kwargs['options']);
I prefer this:
return json_decode($json, $assoc, $depth, $options);
So I use extract()
https://www.php.net/manual/en/function.extract.php to wrap the union above.
Reading the file
I put the file contents in the $json
variable which is json_decode()
's first argument.
$json = @file_get_contents($filename, $use_include_path);
I suppress errors (@
) that would trigger file_get_contents()
if there was an error reading a file.
I know that a json_decode(NULL)
call will result in NULL
without errors.
I don't need Exception handling in json_read()
; I can let it return NULL
.
Decoding JSON
return json_decode($json, $assoc, $depth, $options);
Tests in console
$filename = 'https://openlibrary.org/api/books?bibkeys=ISBN:0385472579,LCCN:62019420&format=json';
$json = json_read($filename);
var_dump($json);
Result:
array(2) {
'ISBN:0385472579' =>
array(5) {
'bib_key' =>
string(15) "ISBN:0385472579"
'preview' =>
string(6) "noview"
'thumbnail_url' =>
string(48) "https://covers.openlibrary.org/b/id/240726-S.jpg"
'preview_url' =>
string(51) "https://openlibrary.org/books/OL1397864M/Zen_speaks"
'info_url' =>
string(51) "https://openlibrary.org/books/OL1397864M/Zen_speaks"
}
'LCCN:62019420' =>
array(4) {
'bib_key' =>
string(13) "LCCN:62019420"
'preview' =>
string(6) "noview"
'preview_url' =>
string(69) "https://openlibrary.org/books/OL5857365M/The_adventures_of_Tom_Sawyer"
'info_url' =>
string(69) "https://openlibrary.org/books/OL5857365M/The_adventures_of_Tom_Sawyer"
}
}
$filename = 'https://openlibrary.org/api/books?bibkeys=ISBN:0385472579,LCCN:62019420&format=json';
$json = json_read($filename, ['assoc'=>FALSE]);
var_dump($json);
Result:
class stdClass#2 (2) {
public $ISBN:0385472579 =>
class stdClass#1 (5) {
public $bib_key =>
string(15) "ISBN:0385472579"
public $preview =>
string(6) "noview"
public $thumbnail_url =>
string(48) "https://covers.openlibrary.org/b/id/240726-S.jpg"
public $preview_url =>
string(51) "https://openlibrary.org/books/OL1397864M/Zen_speaks"
public $info_url =>
string(51) "https://openlibrary.org/books/OL1397864M/Zen_speaks"
}
public $LCCN:62019420 =>
class stdClass#3 (4) {
public $bib_key =>
string(13) "LCCN:62019420"
public $preview =>
string(6) "noview"
public $preview_url =>
string(69) "https://openlibrary.org/books/OL5857365M/The_adventures_of_Tom_Sawyer"
public $info_url =>
string(69) "https://openlibrary.org/books/OL5857365M/The_adventures_of_Tom_Sawyer"
}
}
PHP kwargs are kweasy.