Skip to content

Instantly share code, notes, and snippets.

@TorbenKoehn
Last active December 19, 2015 02:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TorbenKoehn/5885677 to your computer and use it in GitHub Desktop.
Save TorbenKoehn/5885677 to your computer and use it in GitHub Desktop.
PHP Autoboxing: What it could look like I don't think, multiple autoboxing-functions make sense, a __autobox would indeed be more useful than spl_autobox_register, since you can't "merge" multiple classes defined on autoboxes and frameworks require specific functions. The best way would be enabling/disabling the autoboxing in frameworks, set it …
<?php
class Type {
protected $value;
public function __construct( $value ) { $this->value = $value; }
abstract public function __cast( /* (string) Class name */ $type );
}
class String extends Type {
public function toUppercase() {
$this->value = strtoupper( $this->value );
return $this;
}
public function toLowercase() {
$this->value = strtolower( $this->value );
return $this;
}
public function toArray() {
for( $i = 0; $i < strlen( $this->value ); $i++ )
yield $this->value[ $i ];
}
public function __cast( $type ) {
switch( $type ) {
case 'Integer':
return intval( $this->value );
case 'Array':
return $this->toArray();
}
}
}
class Integer extends Type {
public function add( $int ) { $this->value += $int; return $this; }
public function sub( $int ) { $this->value -= $int; return $this; }
public function div( $int ) { $this->value /= $int; return $this; }
public function mul( $int ) { $this->value *= $int; return $this; }
public function rangeFrom( $int ) {
for( $i = $int; $i < $this->value; $i++ )
yield $i;
}
public function rangeTo( $int ) {
for( $i = $this->value; $i < $int; $i++ )
yield $i;
}
public function __cast( $type ) {
switch( $type ) {
case 'String':
return strval( $this->value );
case 'Array':
return $this->rangeFrom( 0 );
}
}
}
class Array {
public function forEach( $callback ) {
foreach( $this->value as $k => $val ) {
$result = call_user_func( $callback, $val, $k );
if( !is_null( $result ) )
$this->value[ $k ] = $result;
}
return $this;
}
public function __cast( $type ) {
switch( $type ) {
case 'String':
$str = '';
$this->forEach( function( $v ) use( $str ) { $str .= $v } );
return $str;
case 'Integer':
throw new Exception( "Invalid cast from array to integer (how shud i do eet?)" );
}
}
}
/* Autoboxing initialization */
if( function_exists( '__autobox' ) )
throw new Exception( "Sorry, autoboxing can only be used ONCE per project. "
. "Anything else would make no sense, other than with __autoload" );
function __autobox( $primitiveType, $value ) {
switch( $primitiveType ) {
case 'string':
return new String( $value );
case 'int':
return new Integer( $value );
case 'array':
return new Array( $value );
}
}
/* Possibilities */
$str = 'my string';
var_dump( $str->toUppercase() ); //str.value = 'MY STRING'
var_dump( $str->toLowercase()->toUppercase() ); //str.value = 'MY STRING'
$int = 14;
var_dump( $int->mul( 2 ) ); //int.value = 28
var_dump( $int->rangeFrom( 5 ) ); //(Array)[5,6,7,...,27,28]
$arr = [ 0, 1, 2, 3, 4, 5 ];
$arr->forEach( function( $i ) {
echo $i;
//!! return value could re-map the values easily
return $i * $i;
} );
var_dump( $arr ); //arr.value = [0,2,4,9,16,25]
/* Type casting */
$str = 'test';
$arr = (Array)$str;
var_dump( $arr ); //arr.value = ['t','e','s','t']
$int = 5;
$str = (String)$int;
var_dump( $int ); //int.value = '5'
$arr = (Array)$int;
var_dump( $arr ); //arr.value = [0,1,2,3,4,5]
<?php
/* This is what __autobox with namespaces could look like */
namespace MyNs;
//this would count for \MyNs and \MyNs\*, all subnamespaces
function __autobox( $primitiveType, $value ) {
//...
}
namespace MyNs\SomeSubNs;
//this would overwrite __autobox of \MyNs, but only for \MyNs\SomeSubNs and \MyNs\SomeSubNs\*
function __autobox( $primitiveType, $value ) {
//...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment