3v4l.org

run code in 300+ PHP versions simultaneously
<?php class Stuff { public static function countObjTypes( array $data, array $types ) { $return['Other'] = 0; foreach ( $types as $type ) $return[$type] = 0; foreach ( ( array ) $data as $obj ) { $set = false; array_walk( $types, function( $type ) use ( $obj, &$return, &$set ) { if ( is_a( $obj, $type ) ) { $return[$type]++; $set = true; } } ); if ( !$set ) $return['Other']++; } return $return; } public static function getArrayValueByPath($array, $path) { #$path = (array) array_filter( $path ); if( !empty( $path ) ) { foreach ( $path as $key ) if( !isset( $array[$key] ) ) return NULL; $array = $array[$key]; return $array; } else { return false; } } } class formRenderer { protected $dom; public function __construct() { $this->dom = new DOMDocument; } public function checkData( $data ) { if( isset( $data[ 'node' ] ) ) throw new Exception('Invalid data, contained node'); return $data; } public function save( $type = 'HTML' ) { $function = 'save'.strtoupper( $type ); return $this->dom->$function(); } public function base( $data ) { extract( $this->checkData( $data ) ); $node = $this->dom->createElement( 'input' ); $node->setAttribute( 'name', $name ); $node->setAttribute( 'id', $name ); $node->setAttribute( 'type', $type ); if( isset( $classes ) ) $node->setAttribute( 'class', $classes ); if( isset ( $value ) ) $node->setAttribute( 'value', $value ); if( isset ( $autocomplete ) ) $node->setAttribute( 'autocomplete', $autocomplete ); $this->form->appendChild( $node ); return $this->dom; } public function Label( $data ) { extract( $this->checkData( $data ) ); $node = $this->dom->createElement( 'label' ); $node->setAttribute( 'for', $for ); $textNode = $this->dom->createDocumentFragment(); $textNode->appendXML( $value ); $node->appendChild( $textNode ); $this->form->appendChild( $node ); return $this->dom; } public function Form( $data ) { extract( $this->checkData( $data ) ); $this->form = $this->dom->createElement( 'form' ); $this->form->setAttribute( 'method', $method ); $this->form->setAttribute( 'name', $name ); $this->dom->appendChild( $this->form ); return $this->dom; } public function HTML( $data ) { extract( $this->checkData( $data ) ); $node = $this->dom->createDocumentFragment(); $node->appendXML( $html ); $this->form->appendChild( $node ); return $this->dom; } } class Form { protected $name; protected $type; protected $data; protected $structure; protected $formRenderer; public function __construct( $name , $method = 'POST' ) { $cleanMethod = strtoupper( $method ); if ( $cleanMethod == 'POST' || $cleanMethod == 'GET' ) { $this->method = $cleanMethod; } else throw new Exception( "Unknown method requested for form $name"); $this->name = $name; $this->collectData( ); } private function collectData( ) { $dataVar = '_'.$this->method; if ( !empty( $GLOBALS[$dataVar] ) ) $this->data = $GLOBALS[$dataVar][$this->name]; } public function addField( Field $field ) { return $this->structure[] = $field->setForm( $this->name, $this->data ); } public function addGroup( Group $group ) { return $this->structure[] = $group->setForm( $this->name, $this->data ); } public function render( formRenderer $renderer = NULL ) { $this->renderer = ( isset( $renderer ) ) ? $renderer : new formRenderer; $this->renderer->Form( array( 'method' => $this->method, 'name' => $this->name ) ); $renderer = $this->renderer; foreach( $this->structure as $structure ) $renderer = $structure->render( $renderer ); return $renderer->save(); } public function isSubmitted( ) { // Check whether we have GET/POST data for some stuff, which will tell us if it was submitted return ( isset( $this->data ) ); } public function validate( ) { foreach( $this->structure as $structure ) $structure->validate(); // Loop through validators. Pass in $data['FieldName']; // Or maybe, get fields to validate themself, using validators. Point is, each $data == a value for a $this->fields } } abstract class Group { protected $data; protected $structure = array(); public function addFeild( Field $field ) { $this->structure[] = $field; } public function setForm( $name, $data ) { $this->data = $data; foreach( $this->structure as $obj ) $obj->setForm( $name, $data ); return $this; } public function render( $renderer ) { $dataCount = array(); foreach( $this->structure as $obj ) $dataCount[] = $obj->getDataGroup( true ); $iterations = ( max( $dataCount ) === 0 ) ? 1 : max( $dataCount ) ; for ( $i = 0; $i < $iterations ; $i++ ) { foreach( $this->structure as $obj ) { $obj->setIteration( $i ); $obj->render( $renderer ); } } return $renderer; } public function validate( ) { foreach( $this->structure as $obj ) $obj->validate( ); } } class QuestionGroup extends Group { public function __construct( LabelField $label, Field $input ) { $this->structure[0] = $label; $this->structure[1] = $input; } } class HoneyPotGroup extends Group { public function __construct( HoneyPotField $timeCheck, HoneyPotField $empty ) { $this->structure[0] = $timeCheck; $this->structure[1] = $empty; } } abstract class Field { protected $vars = array(); private static $id = 0; private $iteration = 0; private $validators = array( ); private $staticValue = FALSE; private $validate = FALSE; private $data; final public function setName( ) { if( !isset( $this->vars['name'] ) ) { $this->uid = self::$id++; return $this->vars['name'] = $this->formName.'['.$this->uid.'][]'; } else { throw new Exception("Attempted to create unique, unique already excists"); } } final public function setData( ) { $this->data = Stuff::getArrayValueByPath( $this->formData, array( $this->uid ) ); } final public function setIteration( $iteration = NULL) { $this->iteration = $iteration; } final public function getDataGroup( $count = FALSE ) { if( $count ) return count( array_filter( (array) $this->data ) ); else return $this->data; } public function setType( $type ) { $this->vars['type'] = $type; } public function setValue( $value, $type = NULL ) { if( isset( $type ) ) $this->vars['value'.ucfirst( $type )] = $value; else $this->vars['value'] = $value; } public function getValue( $type = NULL ) { if( isset( $type ) ) { if( isset( $this->vars['value'.ucfirst( $type )] ) ) { return $this->vars['value'.ucfirst( $type )]; } } else { return $this->vars['value']; } return NULL; } public function getValidatorValue() { $value = $this->getValue( 'validator' ); if( isset( $value ) ) return $this->getValue( 'validator' ); else return $this->getValue(); } public function setStaticValue( $value ) { $this->staticValue = TRUE; $this->setValue( $value ); } public function setForm( $name, $data ) { $this->formData = $data; $this->formName = $name; $this->setName(); $this->setData(); return $this; } public function validator( Validator $validator ) { $this->validators[] = $validator; } public function validate( ) { $this->validate = TRUE; // if( $this->data ) // { // foreach( $this->data as $value ) { // foreach ( $this->validators as $validator ) { // $validator->setValue( $value ); // $validator->validate( ); // } // } // } } public function render( $renderer ) { $function = ucwords( $this->vars['type'] ); $value = Stuff::getArrayValueByPath( $this->data, array( $this->iteration ) ); if( $this->staticValue === FALSE ) $this->setValue( $value ); else $this->setValue( $value, 'validator' ); if( $this->validate ) { foreach( $this->validators as $validator ) { $validator->setValue( $this->getValidatorValue() ); var_dump( $validator->validate() ); } } if( method_exists( $renderer, $function ) ) $renderer->$function( $this->vars ); else $renderer->base( $this->vars ); return $renderer; } } class ActionField extends Field { public function __construct( $value = NULL ) { $this->vars['type'] = 'submit'; if( isset( $value ) ) $this->vars['value'] = $value; } } class UploadField extends Field { public function __construct() { $this->vars['type'] = 'file'; } } class LabelField extends Field { public function __construct( $text = 'Untitled' ) { $this->vars['type'] = 'label'; $this->setStaticValue( $text ); } public function setForm( $name, $data ) { parent::setForm( $name, $data ); $this->vars['for'] = $this->formName.'['.($this->uid + 1).'][]'; return $this; } } class TextField extends Field { public function __construct() { $this->vars['type'] = 'text'; } } class HtmlField extends Field { public function __construct( $html ) { $this->vars['type'] = 'html'; $this->vars['html'] = $html; } } class HiddenField extends Field { public function __construct() { $this->vars['type'] = 'hidden'; } } class HoneyPotField extends Field { public function __construct( $value = NULL ) { $this->vars['type'] = 'text'; $this->vars['classes'] = 'hc'; $this->vars['autocomplete'] = 'off'; $this->setStaticValue( $value ); } } class InputField extends Field { public function __construct( $type ) { $this->vars['type'] = $type; } } class Validator { protected $failureText = array( ); protected $results = array( ); protected $rules = array( ); private $valid = TRUE; final public function __construct( Rule $rule ) { $this->rules[] = $rule; return $this; } final public function addRule( Rule $rule ) { $this->rules[] = $rule; return $this; } public function valid( $returnFailureText = false ) { return ( $returnFailureText ) ? $this->failureText[] = $returnFailureText : $this->valid; } private function invalidate( $failureText ) { $this->valid( $failureText ); $this->valid = false; } public function setValue( $value ) { foreach( $this->rules as $rule ) $rule->setValue( $value ); } public function validate( ) { foreach ( $this->rules as $rule ) { $result = $this->results[] = $rule->validate( ); if ( $result === FALSE ) { $this->invalidate( $rule->getFailureText() ); } } $this->getErrors(); return $this->valid; } public function getErrors() { return $this->failureText; } } abstract class Rule { protected $limit; protected $value; protected $failureText; final public function __construct( $failureText, $limit = NULL, $value = NULL ) { $this->failureText = $failureText; $this->limit = $limit; $this->value = $value; } final public function setValue( $value ) { $this->value = $value; return $this; } final public function getFailureText() { return $this->failureText; } } class GreaterThanRule extends Rule { public function validate( ) { return $this->result = ( $this->value > $this->limit ); } } class LessThanRule extends Rule { public function validate( ) { return $this->result = ( $this->value < $this->limit ); } } class ValidEmailRule extends Rule { public function validate( ) { return $this->result = filter_var( $this->value, FILTER_VALIDATE_EMAIL ); } } class ValidUrlRule extends Rule { public function validate( ) { return $this->result = filter_var( $this->value, FILTER_VALIDATE_URL ); } } class ValidNameRule extends Rule { public function validate( ) { return $this->result = ctype_print( $this->value ); } } class NumericRule extends Rule { public function validate( ) { return $this->result = is_numeric( $this->value ); } } class TextRule extends Rule { public function validate( ) { return $this->result = ctype_alpha( $this->value ); } } class StringLengthGreaterThanRule extends Rule { public function validate( ) { return $this->result = ( strlen( $this->value ) > $this->limit ); } } class StringLengthLessThanRule extends Rule { public function validate( ) { return $this->result = ( strlen( $this->value ) < $this->limit ); } } class DateCheckRule extends Rule { public function validate( ) { return $this->result = strtotime( $this->value ); } } class HoneyPotTimeRule extends Rule { public function validate( ) { $limit = ( isset( $this->limit ) ) ? $this->limit : 2; return $this->result = ( ( $this->value + $limit ) <= time() ); } } class EqualRule extends Rule { public function validate( ) { return $this->result = ( $this->value === $this->limit ); } } // An example of how to use it $form = new Form( 'Form', 'post' ); $honeyPot1 = new HoneyPotField( time() ); $honeyPot1->validator( new Validator( new HoneyPotTimeRule( 'This form was filled in too quickly, assumed bot, please allow 2 seconds to fill in the form' ) ) ); $honeyPot2 = new HoneyPotField(); $honeyPot2->validator( new Validator( new EqualRule( 'This field was unexpectedly filled in, assumed bot', '' ) ) ); $q1l = new LabelField( 'Question 1' ); $q1 = new InputField( 'text' ); $q2l = new LabelField( 'Question 2' ); $q2 = new InputField( 'text' ); $form->addGroup( new HoneyPotGroup( $honeyPot1, $honeyPot2 ) ); $form->addGroup( new QuestionGroup( $q1l, $q1 ) ); $form->addGroup( new QuestionGroup( $q2l, $q2 ) ); $form->addField( new UploadField( 'text' ) ); $form->addField( new ActionField( 'Send' ) ); if( $form->isSubmitted() ) $form->validate( ); echo $form->render( ); // outputs the form + elements

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
7.1.00.0100.06322.54
7.0.140.0070.06322.21
7.0.110.0070.08320.24
7.0.100.0100.07720.25
7.0.90.0170.07020.20
7.0.80.0130.07320.19
7.0.70.0170.04020.21
7.0.60.0030.09020.31
7.0.50.0100.07320.34
7.0.40.0070.07019.80
7.0.30.0130.07319.86
7.0.20.0200.07019.82
7.0.10.0070.08319.73
7.0.00.0030.08319.85
5.6.280.0070.07321.36
5.6.260.0130.07320.89
5.6.250.0100.05020.83
5.6.240.0070.08320.75
5.6.230.0130.07320.99
5.6.220.0030.09020.80
5.6.210.0100.07020.84
5.6.200.0030.09320.85
5.6.190.0100.04020.90
5.6.180.0000.09020.86
5.6.170.0070.08020.83
5.6.160.0130.06320.94
5.6.150.0100.07020.73
5.6.140.0100.06720.86
5.6.130.0030.08320.85
5.6.120.0130.08020.78
5.6.110.0070.08020.78
5.6.100.0070.08720.78
5.6.90.0170.06720.77
5.6.80.0030.07720.28
5.6.70.0100.07020.23
5.6.60.0070.07720.29
5.6.50.0170.06320.23
5.6.40.0130.05720.15
5.6.30.0100.07720.29
5.6.20.0030.08020.20
5.6.10.0130.04020.14
5.6.00.0030.08720.19
5.5.380.0100.07720.75
5.5.370.0130.07720.59
5.5.360.0070.04020.74
5.5.350.0100.08020.76
5.5.340.0230.06721.27
5.5.330.0270.03021.19
5.5.320.0030.04321.05
5.5.310.0130.07721.06
5.5.300.0070.07321.13
5.5.290.0130.04321.22
5.5.280.0030.09020.94
5.5.270.0070.06721.15
5.5.260.0070.05021.14
5.5.250.0070.08321.00
5.5.240.0170.07320.62
5.5.230.0070.07720.62
5.5.220.0070.08020.42
5.5.210.0070.08020.61
5.5.200.0070.07720.50
5.5.190.0030.08020.54
5.5.180.0030.07720.29
5.5.160.0130.06720.54
5.5.150.0070.06720.43
5.5.140.0000.07720.58
5.5.130.0100.07320.49
5.5.120.0070.06720.40
5.5.110.0170.07320.39
5.5.100.0170.06720.49
5.5.90.0070.07720.49
5.5.80.0030.05720.23
5.5.70.0070.08020.21
5.5.60.0100.04720.37
5.5.50.0100.08320.25
5.5.40.0070.05020.21
5.5.30.0170.07720.36
5.5.20.0130.07720.36
5.5.10.0130.07320.50
5.5.00.0100.07720.46
5.4.450.0070.08319.52
5.4.440.0130.07319.84
5.4.430.0100.07319.49
5.4.420.0070.08019.50
5.4.410.0030.04719.32
5.4.400.0070.07319.36
5.4.390.0100.07319.14
5.4.380.0100.07019.27
5.4.370.0070.06019.16
5.4.360.0100.06719.18
5.4.350.0100.06319.46
5.4.340.0170.07019.26
5.4.320.0130.06019.14
5.4.310.0130.07319.23
5.4.300.0230.06019.17
5.4.290.0070.04719.35
5.4.280.0130.04019.19
5.4.270.0030.08019.14
5.4.260.0070.05719.10
5.4.250.0130.04019.45
5.4.240.0070.06719.46
5.4.230.0130.06319.28
5.4.220.0130.07719.19
5.4.210.0070.08019.45
5.4.200.0100.07719.19
5.4.190.0030.07719.27
5.4.180.0030.08019.45
5.4.170.0070.07319.45
5.4.160.0100.06719.36
5.4.150.0070.07319.15
5.4.140.0100.06716.55
5.4.130.0030.04716.68
5.4.120.0000.08016.63
5.4.110.0070.07016.71
5.4.100.0100.07316.86
5.4.90.0030.07316.77
5.4.80.0000.08016.75
5.4.70.0030.04316.79
5.4.60.0200.06016.66
5.4.50.0030.04716.66
5.4.40.0170.03316.77
5.4.30.0100.06316.49
5.4.20.0130.07316.61
5.4.10.0070.07016.72
5.4.00.0130.07016.18
5.3.290.0100.06015.31
5.3.280.0100.06715.09
5.3.270.0030.04715.16
5.3.260.0030.07315.21
5.3.250.0030.07315.12
5.3.240.0130.07015.11
5.3.230.0100.07715.03
5.3.220.0130.07315.06
5.3.210.0030.08315.00
5.3.200.0000.07314.96
5.3.190.0100.07715.21
5.3.180.0130.06314.99
5.3.170.0130.06015.11
5.3.160.0070.07314.98
5.3.150.0100.06715.05
5.3.140.0030.07714.95
5.3.130.0070.07315.04
5.3.120.0070.04715.05
5.3.110.0000.05315.08
5.3.100.0000.08314.59
5.3.90.0100.04014.45
5.3.80.0130.06314.55
5.3.70.0070.05714.43
5.3.60.0000.05014.64
5.3.50.0100.07014.36
5.3.40.0170.07014.36
5.3.30.0100.07014.39
5.3.20.0130.06314.27
5.3.10.0070.07314.27
5.3.00.0130.07014.27

preferences:
1556.59 ms | 1398 KiB | 21 Q