4

在我正在创建的应用程序中,我需要将未知数量的参数传递给类的未知构造函数。类(+ 命名空间)是一个字符串,在 $class 中。参数在一个数组中。

这个应用程序将在几个月内部署,所以我们认为我们可以在 PHP 5.6 中开发它。所以我认为这个问题的解决方案是:

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

这是工作...

但是我的同事们并不想接受这个,因为CI服务器不理解这行代码。他们的解决方案宁愿是:

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

现在:两者都工作正常,所以这不是问题。但我的想法是反射比使用其他方式(如 PHP 5.6 splat 运算符)要慢。

还有一个问题:反射是一种好方法,我应该从 CI 服务器理解那条线的那一刻起使用 splat 运算符吗?

4

2 回答 2

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);?

于 2014-07-08T14:27:51.530 回答
7

今天,我找到了对它进行基准测试的时间。
就像我预期的那样(Fleshgrinder 说):splat 运算符更快。

基准时间:
反射:11.686084032059s
Splat:6.8125338554382s

差不多一半的时间……那是认真的……

基准测试(通过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;
于 2014-07-09T08:20:45.830 回答