Skip to content

Instantly share code, notes, and snippets.

@mikeschinkel
Last active January 13, 2020 01:26
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 mikeschinkel/e07eb14a34ce83a96198744e18b0c961 to your computer and use it in GitHub Desktop.
Save mikeschinkel/e07eb14a34ce83a96198744e18b0c961 to your computer and use it in GitHub Desktop.
Brainstorming on a concept for PHP I am calling "Projection" here.

Brainstorming on a concept for PHP I am calling "Projection" here. This could be a new API for PHP or just extensions to Reflection.

The examples below are far from complete and I am sure there are missing aspects in some of these interfaces as this is just an exploration of concept and not something fully tested.

Note that I used leading underscores on file names to order which files are displayed by Gist above the other files, except for _Class, _Interface and _Trait which have leading underscores to match the class names, because class, interface and trait are reserved words in PHP.

<?php
/**
* This illustrates how Projection might work to create a class
*/
$class = new ProjectionClass( 'ShoppingCart' );
$property = new ProjectionProperty( '_items' );
$property->setType( new ProjectionType( Projection::ARRAY ) );
$property->setDefaultValue( [] );
$property->setPrivate( true );
$class->addProperty( $property );
$method = new ProjectionMethod( 'add_item' );
$parameter = new ProjectionParameter( 'item_id' );
$parameter->setType( new ProjectionType( Projection::INT ) );
$method->addParameter( $parameter );
$method->setClosure( function ( string $item_id ) {
self::$_items[] = $item_id;
} );
$class->addMethod( $method );
$method = new ProjectionMethod( 'get_items' );
$method->setType( new ProjectionType( Projection::ARRAY ) );
$method->setClosure( function () {
return self::$_items;
} );
$class->addMethod( $method );
Projection::declare( $class );
$cart = new ShoppingCart();
$cart->add_item( 'ABC-123' );
print_r( $cart->get_items() );
<?php
class Projection {
const ARRAY = 'array';
const INT = 'int';
static function declare( $projector ) {
// Implement code to generate OpCode for the independent language element
}
}
<?php
use Projection\ClassConstant;
use Projection\Property;
use Projection\Method;
class ProjectionClass implements Projection\_Class {
public function __construct( string $name ) { }
function setNamespace( string $namespace_name ) {
// TODO: Implement setNamespace() method.
}
function addConstant( ClassConstant $constant ) {
// TODO: Implement addConstant() method.
}
function addProperty( Property $property ) {
// TODO: Implement addProperty() method.
}
function setParent( string $class_name ) {
// TODO: Implement setParent() method.
}
function addInterface( string $interface_name ) {
// TODO: Implement addInterface() method.
}
function toReflectionClass(): ReflectionClass {
// TODO: Implement toReflectionClass() method.
return new ReflectionClass('');
}
function addMethod( Method $method ) {
// TODO: Implement addMethod() method.
}
function addTrait( string $trait_name ) {
// TODO: Implement addTrait() method.
}
}
<?php
use Projection\Type;
use Projection\Parameter;
class ProjectionMethod implements Projection\Method {
public function __construct( string $name ) { }
function setStatic( bool $isStatic ) {
// TODO: Implement setStatic() method.
}
function setPublic( bool $isPublic ) {
// TODO: Implement setPublic() method.
}
function setPrivate( bool $isPrivate ) {
// TODO: Implement setPrivate() method.
}
function setProtected( bool $isProtected ) {
// TODO: Implement setProtected() method.
}
function setClosure( Closure $method ) {
// TODO: Implement setClosure() method.
}
function setType( Type $type ) {
// TODO: Implement setType() method.
}
function addParameter( Parameter $parameter ) {
// TODO: Implement addParameter() method.
}
}
<?php
use Projection\Type;
class ProjectionParameter implements Projection\Parameter {
public function __construct( string $name ) { }
function setDefaultValue( $value ) {
// TODO: Implement setDefaultValue() method.
}
function setType( Type $type ) {
// TODO: Implement setType() method.
}
}
<?php
use \Projection\Type;
class ProjectionProperty implements Projection\Property {
public function __construct( string $name ) { }
function setStatic( bool $isStatic ) {
// TODO: Implement setStatic() method.
}
function setDefaultValue( $value ) {
// TODO: Implement setDefaultValue() method.
}
function setDocComment( string $comment ) {
// TODO: Implement setDocComment() method.
}
function setPublic( bool $isPublic ) {
// TODO: Implement setPublic() method.
}
function setPrivate( bool $isPrivate ) {
// TODO: Implement setPrivate() method.
}
function setProtected( bool $isProtected ) {
// TODO: Implement setProtected() method.
}
function setType( Type $type ) {
// TODO: Implement setType() method.
}
function setValue( $value ) {
// TODO: Implement setValue() method.
}
}
<?php
class ProjectionType implements Projection\Type {
public function __construct( string $name ) { }
function setAllowsNull( bool $allowsNull ) {
// TODO: Implement setAllowsNull() method.
}
function toReflectionType(): ReflectionType {
// TODO: Implement toReflectionType() method.
return new ReflectionType();
}
function __toString(): string {
// TODO: Implement __toString() method.
return '';
}
}
<?php
namespace Projection;
use ReflectionClass;
interface _Class extends
Named,
CanBeNamespaced,
CanImplementInterfaces,
CanUseTraits,
CanHaveOneParent,
CanDeclareConstants,
CanDeclareMethods,
CanDeclareProperties {
function toReflectionClass():ReflectionClass;
}
<?php
namespace Projection;
interface _Interface extends
Named,
CanHaveManyParents,
CanBeNamespaced,
CanDeclareConstants,
CanDeclareMethods,
CanDeclareProperties {
}
<?php
namespace Projection;
interface _Trait extends
Named,
CanBeNamespaced,
CanDeclareMethods,
CanDeclareProperties {
function setAlias(string $alias);
}
<?php
namespace Projection;
interface CanBeNamespaced {
function setNamespace( string $namespace_name );
}
<?php
namespace Projection;
interface CanBeStatic {
function setStatic(bool $isStatic);
}
<?php
namespace Projection;
interface CanDeclareConstants {
function addConstant( ClassConstant $constant );
}
<?php
namespace Projection;
interface CanDeclareMethods {
function addMethod( Method $method );
}
<?php
namespace Projection;
interface CanDeclareProperties {
function addProperty( Property $property );
}
<?php
namespace Projection;
interface CanHaveDefault {
function setDefaultValue($value);
}
<?php
namespace Projection;
interface CanHaveDocComment {
function setDocComment(string $comment);
}
<?php
namespace Projection;
interface CanHaveManyParents {
function addParent( string $interface_name );
}
<?php
namespace Projection;
interface CanHaveOneParent {
function setParent( string $class_name );
}
<?php
namespace Projection;
interface CanHaveParameters {
function addParameter(Parameter $parameter);
}
<?php
namespace Projection;
interface CanImplementInterfaces {
function addInterface( string $interface_name );
}
<?php
namespace Projection;
interface CanUseTraits {
function addTrait( string $trait_name );
}
<?php
namespace Projection;
interface ClassConstant extends
Constant,
HasVisibility,
CanHaveDocComment {
}
<?php
namespace Projection;
interface Constant extends
NamedAndValued,
Typed,
Valued {
}
<?php
namespace Projection;
interface HasVisibility {
function setPublic(bool $isPublic);
function setPrivate(bool $isPrivate);
function setProtected(bool $isProtected);
}
<?php
namespace Projection;
use Closure;
interface Method extends
Named,
CanBeStatic,
CanHaveParameters,
HasVisibility,
Typed {
function setClosure(Closure $method);
}
<?php
namespace Projection;
interface Named {
function __construct(string $name);
}
<?php
namespace Projection;
interface NamedAndValued {
function __construct(string $name, $value);
}
<?php
namespace Projection;
interface Parameter
extends Named, Typed, CanHaveDefault {
}
<?php
namespace Projection;
interface Property extends
Named,
Typed,
CanBeStatic,
HasVisibility,
CanHaveDocComment,
CanHaveDefault,
Valued {
}
<?php
namespace Projection;
interface toString {
function __toString(): string;
}
<?php
namespace Projection;
use ReflectionType;
interface Type extends
Named,
toString {
function setAllowsNull(bool $allowsNull);
function toReflectionType():ReflectionType;
}
<?php
namespace Projection;
interface Typed {
function setType(Type $type);
}
<?php
namespace Projection;
interface Valued {
function setValue($value);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment