问题 PHP动态类加载


让我们说我有一个我想要转换为值对象的数组。

我的值对象类如下:

/* file UserVO.php*/
 class UserVO
 {
    public $id;
    public $email;

     public function __construct($data)
     {
         $this->id = (int)$data['id'];
         $this->email = $data['email'];
     } 
 }

我创建了我的值对象数组,如下所示:

/* file UserService.php*/
$array = array(
array(...),
array(...));
$count = count($array);
for ($i = 0; $i < $count; $i++)
{
   $result[] = new UserVO($array[$i]);
}
return $result;

好的,所以一切正常。但是,我想具体说明要动态创建的VO,这样我就可以使用一个动态函数来创建我的VO。

就像是:

$ret = create_vo($array, 'UserVO');

function create_vo($data, $vo)
{
  $count = count($data);
  for ($i = 0; $i < $count; $i++)
  {
     $result[] = new $vo($data[$i]); //this obviously wont work...Class name must be a valid object or a string
  }
  return $result;
}

我意识到我可以通过switch语句(迭代我所有的VO)来做到这一点......但毫无疑问,这是一个更加优雅的解决方案。如果我可以根据需要懒得加载VO,而不是多个'包含',它也会是超酷的

任何帮助非常感谢。


10967
2017-09-10 15:24


起源



答案:


$result[] = new $vo($data[$i]); //this obviously wont work...Class name must be a valid object or a string

你试过吗?它的工作原理与预期一样(在php 5.1中,我不知道它是如何在PHP 4中使用OOP,但如果你正在使用它 __construct 对于构造函数,这应该工作)。

避免多重包含定义魔术功能 __autoload 在使用任何课程之前

function __autoload($className)
{
    require_once 'myclasses/'.$className.'.php';
}

所以先打个电话 new UserVo 将触发此功能以包含文件 myclasses / UserVo.php


13
2017-09-10 15:37





看起来 include_once()和require_once()的性能非常糟糕

我的建议:

杀死所有“require_once”和“include_once”并创建自动加载器。注册这个 履行


1
2018-06-01 14:21



你的自动加载器仍然使用include或要求它不会只在需要时不加载所有东西,所以你的参数不是最有效的。因为使用自动加载器更加负载。 - Martin Barker


答案:


$result[] = new $vo($data[$i]); //this obviously wont work...Class name must be a valid object or a string

你试过吗?它的工作原理与预期一样(在php 5.1中,我不知道它是如何在PHP 4中使用OOP,但如果你正在使用它 __construct 对于构造函数,这应该工作)。

避免多重包含定义魔术功能 __autoload 在使用任何课程之前

function __autoload($className)
{
    require_once 'myclasses/'.$className.'.php';
}

所以先打个电话 new UserVo 将触发此功能以包含文件 myclasses / UserVo.php


13
2017-09-10 15:37





看起来 include_once()和require_once()的性能非常糟糕

我的建议:

杀死所有“require_once”和“include_once”并创建自动加载器。注册这个 履行


1
2018-06-01 14:21



你的自动加载器仍然使用include或要求它不会只在需要时不加载所有东西,所以你的参数不是最有效的。因为使用自动加载器更加负载。 - Martin Barker


这很有效

<?

class UserVO
{
    public $id;
    public $email;

    public function loadData($data)
    {
        $this->id = (int)$data['id'];
        $this->email = $data['email'];
    }
}

function create_vo($data, $vo)
{
    $count = count($data);
    for ($i = 0; $i < $count; $i++)
    {
        $tmpObject = new $vo;
        $tmpObject->loadData($data[$i]);
        $result[] = $tmpObject;
        unset($tmpObject);
    }
    return $result;
}


$data = array();
$data[] = array('id'=>1,'email'=>'data@example.com');
$data[] = array('id'=>2,'email'=>'data@example.com');
$data[] = array('id'=>3,'email'=>'data@example.com');
$data[] = array('id'=>4,'email'=>'data@example.com');
$data[] = array('id'=>5,'email'=>'data@example.com');
$data[] = array('id'=>6,'email'=>'data@example.com');

$result = create_vo($data,'UserVO');

var_dump($result);

?>

0
2017-09-10 15:41





首先,应使用ArrayObject将数据转换为UserVO的数组对象

所以

class UserVO extends ArrayObject
{
}

你正试图使用 工厂方法模式 并且您的代码似乎是正确的,尽管您似乎忘记将$ result定义为数组($ result = array())。

你也可以使用 ReflectionClass 传递构造函数参数以及如下:

$rc = new ReflectionClass($vo);
$rc->newInstanceArgs($data[$i]);

要“自动加载”您的UserVO对象,您应该使用 spl_autoload_register 功能与PHP包含路径。


0
2017-09-10 15:41