charm / options
A generic class for storing options while enforcing option types.
README
A better way to allow configuration of your library via an options class.
TLDR
Document your library's options like this. If you're targetting PHP 8.1, you should declare the options 'readonly'.
<?php
namespace Some\Namespace;
class MyOptions extends \Charm\AbstractOptions {
const CACHE_OFF = 0;
const CACHE_AUTO = 1;
const CACHE_ON = 2;
/**
* Example option which is required.
*/
public string $apiKey;
/**
* Example option which is not required.
*/
public string $apiSecret = "";
/**
* Example option which must be among the MyOptions::CACHE_* constants.
*/
public int $cache = self::CACHE_AUTO;
/**
* An integer value is required.
*/
public int $ttl = 86400;
}
Constructing via new
keyword
<?php
$options = new Some\Namespace\MyOptions([
'apiKey' => "some-value",
'apiSecret' => "some-secret",
'ttl' => 'short',
]);
Constructing via create()
method
<?php
$options = YourOptions::create([
'apiKey' => "some-value",
'apiSecret' => "some-secret",
'ttl' => 'short',
]);
Mutability
Options are mutable if they are declared public
. They are read-only if they are
declare protected
or private
.
In PHP 8.1 you can use the readonly
keyword on public properties to achieve the same
with a very small performance improvement.
Declare an options class
<?php
class HttpClientOptions extends Charm\AbstractOptions {
/**
* Most permissive option. It is not required, and any scalar value is accepted.
*/
public $anything_goes;
/**
* Class constants with a prefix which is an uppercase of a property name
* is validated and allows only values among those constants.
*/
const CACHE_OFF = 0;
const CACHE_AUTO = 1;
const CACHE_ON = 2;
/**
* Must be set to one of the above constants
*/
public int $cache;
/**
* An strictly typed option which is required since it does not have a default.
*/
public string $base_url;
/**
* Union types are OK if you are targetting PHP 8
*/
public int|bool $either_int_or_boolean;
/**
* Allow nested options by declaring those as well:
*/
public HttpClientCookieOptions $cookie_options;
/**
* Declare this function if you wish to automatically set some options or
* perform custom validation
*/
protected function finalize() {
assert(str_starts_with($this->base_url, 'http', 'URL must start with "http"');
}
}
Setting Options
Options are set in the constructor.
<?php
$httpClient = new HttpClient(new HttpClientOptions([
'anything_goes_not_required' => "Hello World",
'base_url' => 123, // triggers a validation error (not string)
'either_int_or_boolean' => false,
'cookie_options' => [
// configuration options for a HttpClientCookieOptions
],
]));
Reading Options
---------------
Options can be accessed directly as properties.
<?php echo $options->cookie_options->cookie_jar_file;
Alternatives for options that are private:
<?php // Get a stdClass options map $accessibleOptions = $options->asObject(); // you'll receive a new stdClass with all the options
// Read via ArrayAccess interface $theOption = $options['a_private_option']; ?>
Mutating Options
It is okay to create a new instance of the options object if you wish to "inherit" from another instance.
<?php
$heir = new HttpClientOptions(["some_overridden_options" => 123] + $ancestor);
Using an option class
Example provided for completeness.
<?php
class HttpClient {
protected HttpClientOptions $options;
public function __construct(HttpClientOptions $options) {
$this->options = $options;
}
}