4

In an app that I'm creating, I need to pass an unknown number of parameters to an unknown constructor of a class. The class (+ namespace) is a string, that is in $class. The parameters are in an array.

This application will be deployed over a couple of months, so we thought we could develop it already in PHP 5.6. So I thought that the solution of this would be:

$instance = new $class(...$args); 

This is working...

But my collegues don't want to accept this, because the CI server does not understand this line of code. Their solution would rather be:

$reflect = new \ReflectionClass($class); $instance = $reflect->newInstanceArgs($args) 

Now: both are working fine, so that's not the problem. But my thought is that Reflection is slower then using other ways (like the PHP 5.6 splat operator).

Also the question: is reflection a good way, of should I use the splat operator from the moment the CI server does understand that line?

4
  • 1
    Benchmark it either way. Write us a postcard if you find any significant difference. Commented Jul 8, 2014 at 14:20
  • 2
    unknown class? that sounds like a really bad design. Commented Jul 8, 2014 at 14:20
  • Why not use one variable as array of params? Commented Jul 8, 2014 at 14:22
  • Unkown class: at that level I only am sure that it is a class that implements an interface. The method that I'm using is for converting data from one datasource to the data classes. For the method itself the class is unknown, because it's abstract. Commented Jul 9, 2014 at 7:17

2 Answers 2

8

Today I've found the time to benchmark it.
And it's like I've expected (and Fleshgrinder said): the splat operator is faster.

Benchmark times:
Reflection: 11.686084032059s
Splat: 6.8125338554382s

Almost the half of time... That's serious...

Benchmark (via http://codepad.org/jqOQkaZR):

<?php require "autoload.php"; function convertStdToCollectionReflection(array $stds, $entity, $initVars) { $records = array(); $class = $entity . '\\Entity'; foreach ($stds as $record) { $args = array(); foreach ($initVars as $var) { $args[] = $record->$var; } $reflect = new \ReflectionClass($class); $records[] = $reflect->newInstanceArgs($args); } return $records; } function convertStdToCollectionSplat(array $stds, $entity, $initVars) { $records = array(); $class = $entity . '\\Entity'; foreach ($stds as $record) { $args = array(); foreach ($initVars as $var) { $args[] = $record->$var; } $records[] = new $class(...$args); } return $records; } $dummyObject = array(); for ($i = 0; $i < 10; $i++) { $dummyclass = new \stdClass(); $dummyclass->id = $i; $dummyclass->description = 'Just a number... ' . $i; $dummyObject[] = $dummyclass; } print 'Start Reflection test' . PHP_EOL; $reflectionStart = microtime(true); for($i = 0; $i < 1000000; $i++) { convertStdToCollectionReflection( $dummyObject, 'Xcs\Core\Record', array( 'id', 'description' ) ); } $reflectionEnd = microtime(true); print 'Start Splat test' . PHP_EOL; $splatStart = microtime(true); for($i = 0; $i < 1000000; $i++) { convertStdToCollectionSplat( $dummyObject, 'Xcs\Core\Record', array( 'id', 'description' ) ); } $splatEnd = microtime(true); print PHP_EOL . 'OUTPUT:' . PHP_EOL; print 'Reflection: ' . ($reflectionEnd - $reflectionStart) . 's' . PHP_EOL; print 'Splat: ' . ($splatEnd - $splatStart) . 's' . PHP_EOL; 
Sign up to request clarification or add additional context in comments.

3 Comments

Can you post your benchmark. Otherwise your answer is useless.
It's pretty much straight forward, just doing the same job with both the implementations. codepad.org/jqOQkaZR
I was not telling that it is hard :-). I just told that without code which produced these results, results by themselves are useless. +1 for code.
7

Definitely go for the splat operator, why? It's much faster than the reflection approach (I'm using it and the implementation seems to be very good). Also reflection breaks just about anything that has to do with design, it allows you to break encapsulation for instance.

PS: Isn't it $instance = new $class(...$args);?

2 Comments

Yes, was a typo from my side, that's the correct code.
Much faster is not really a good metric. Can you post your benchmark with your finding.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.