Skip to content

Instantly share code, notes, and snippets.

@mikeschinkel
Last active January 24, 2023 05:47
Show Gist options
  • Save mikeschinkel/361bbcf44da1dac0da6afd786b6b8c3a to your computer and use it in GitHub Desktop.
Save mikeschinkel/361bbcf44da1dac0da6afd786b6b8c3a to your computer and use it in GitHub Desktop.
Examples for how a __toArray() magic method could be useful in PHP.

Examples for how a __toArray() magic method could be useful in PHP.

In a nutshell, __toArray() would not be as useful when you have full control over the entire codebase.

But where __toArray() would be extremely useful is in interfacing with existing code that expects arrays and wants those arrays to be a specific format. Using classes and type-hinted methods allow to encapsulate the intelligence into the class, and using __toArray() makes for a nature use-case.

<?php
//
// Use with https://github.com/bobthecow/mustache.php
//
class SaleableItem {
private $id = false;
private $mode = 'edit';
// Other properties go here
function __construct($id) {
$this->id = $id;
}
function load() {
// load data from DB
}
function __toArray():array {
return array(
'id' => 'add' === $this->mode ? null : $this->id,
// Other properties go here
);
}
function forAdd():self {
$this->mode = 'add';
return $this;
}
function forEdit():self {
$this->mode = 'edit';
return $this;
}
}
$item = new SaleableItem('abc123');
$item->load();
$engine = new Mustache_Engine();
echo $engine->render( 'item-form', $item->forAdd() );
<?php
class SaleableItemList {
private $items = array();
function load() {
$items = DB::select("select * from items");
foreach( $items as $item) {
$this->items[] = new SaleableItem($item);
}
}
function __toArray():array {
return $this->items;
}
}
$items = new SaleableItemList();
$items->load();
$names = array_column($items,'name');
$diff_0_vs_1 = array_diff_assoc($items[0],$items[1]);
$intersect_0_vs_1 = array_intersect_assoc($items[0],$items[1]);
$non_empty_props = array_filter($items[0]);
$empty_initial_values = array_fill_keys($items[0],null);
$elementa = array_keys($items[0]);
$sanitized = array_map(['Santizier','sanitize'],$items[0]);
$merged = array_merge_recursive($items[0],$items[1]);
$values = array_values($items[0]);
<?php
class WP_Post {
// Everything that is already in WP_Post
private $mode = 'edit';
function __toArray():array {
$array = get_object_vars($this);
if ('add'===$this->mode) {
$array['ID'] = null;
}
return $array;
}
function forAdd():self {
$this->mode = 'add';
return $this;
}
}
$post = new WP_Post();
// Get $post values from $_POST
wp_insert_post($post->forAdd());
<?php
class Resource {
private $url;
private $params;
function __construct(string $url, array $params) {
$this->url = $url;
$this->params = $params;
}
function __toString():string {
return $this->url;
}
function __toArray():array {
return $this->params;
}
}
class Response {
private $response;
function __construct(string $response) {
$this->response = !is_wp_error($response)
? $response
: array();
}
function __toString():string {
return wp_remote_retrieve_body($this);
}
function __toArray():array {
return (array)$this;
}
function toJson():array {
return json_decode($this);
}
}
$resource = new Resource('http://api.acme.com/widget',['id'=>'abc123']);
$response = new Response( wp_remote_get($resource,$resource) );
echo $response->toJson();
<?php
class AllowedHtml {
private $allowed = array();
public $default = array();
function __construct( $allowed = array() ) {
$this->default = $allowed;
}
function add_tag( string $tag, $attributes = array() ) {
if ( isset( $this->allowed[ $tag ] ) ) {
$attributes = array_merge( $this->allowed[ $tag ], $attributes );
}
$this->allowed[ $tag ] = new AllowedHtml($attributes);
}
function add_tags( array $tags ) {
foreach( $tags as $key => $value ) {
if ( is_array( $value ) ) {
$allowed[ $key ] = new AllowedHtml( $value );
} else {
$allowed[ $value ] = new AllowedHtml();
}
}
}
function __toArray():array {
return array_merge(
$this->default, $this->allowed
);
}
}
/**
* @See The following (mostly) replicates a much longer example from:
* https://wp-mix.com/wordpress-basic-allowed-html-wp_kses/
*/
$allowed_html = new AllowedHtml( [ 'id', 'class', 'title', 'style', 'data' ] );
$allowed_html->add_tags( [ 'abbr', 'b', 'code', 'strike', 'strong', 'em', 'i' ] );
$allowed_html->add_tags( [ 'div', 'span', 'p' ] );
$allowed_html->add_tags( [ 'dd', 'dl', 'dt', 'li', 'ol', 'ul' ] );
$allowed_html->add_tags( [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ] );
$allowed_html->add_tag( 'a', [ 'rel' => [], 'href' => array( '_blank', '_top' ) ] );
$allowed_html->add_tag( 'blockquote', [ 'cite' ] );
$allowed_html->add_tag( 'q', [ 'cite' ] );
$allowed_html->add_tag( 'del', [ 'datetime' ] );
$allowed_html->add_tag( 'img', [ 'alt', 'height', 'width', 'src' ] );
$clean_html = wp_kses(
$_POST[ 'content' ] ?? null,
$allowed_html
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment