【问题标题】:Dynamically load PHP class(es)动态加载 PHP 类
【发布时间】:2016-08-02 05:04:27
【问题描述】:

我已经看过无数关于如何创建动态命名类的示例,但它似乎对我不起作用:

$dynamic_id = 980; // typically passed in

$class = 'API\Recipes\Mix_' . $dynamic_id;
$dyn_class = new $class(); 
// results in: Fatal error: Class 'API\Recipes\Mix_980' not found

$class = "API\Recipes\Mix_{$dynamic_id}";
$dyn_class = new $class(); 
// results in: Fatal error: Class 'API\Recipes\Mix_980' not found

$static_class = new API\Recipes\Mix_980();
// results in: Fatal error: Class 'API\Recipes\Mix_980' not found

我正在尝试使用基于$dynamic_id 值的一些动态加载的类来实现策略模式。所有其他类都加载到这个 Slim 框架应用程序中。我只是添加这些新类。

文件所在的路径包含在composer.json 中以进行自动加载,并且我创建的接口试图动态加载它,但不是动态类。 PHPStorm 在文件或目录上没有给我任何错误。

如果我只是手动加载,PHPStorm 会找到该类的正确路径,但它仍然说它无法加载该类,并出现致命错误,即类不存在。就目前而言,我试图加载的类的全部内容是这样的:

<?php

namespace API\Recipes;

class Mix_980
{
  function __construct()
  {
    echo 'show me the money';
  }
}

我从来没有见过“给我钱”,只得到一个 PHP 致命错误。我怀疑这与命名空间有关,但它是如此基本,应该可以工作。我尝试将Recipes 设置为Recipe 的子目录,重命名它等等。似乎没有任何效果! :(

<?php

namespace API\Recipe;

use API\Recipes\Mix_980;

class Mix implements MixInterface
{
  private $mixType;

  function __construct($item_type_id = 0)
  {
    //$class = "\API\Recipes\Mix_{$item_type_id}";
    //$class = 'API\Recipes\Mix_' . $item_type_id;
    //$class = new Mix_980();
    //$class = '\API\Recipes\Mix_980';
    //echo $class;
    $mix = new \API\Recipes\Mix_980();

  }
}

目录结构:

B$ tree ./src/API/
./src/API/
├── Dir1
├── Dir2
├── . . . 
├── Recipe
│   ├── MixInterface.php
│   ├── Mix.php   // implements MixInterface
│   └── Recipe.php
├── Recipes
│   ├── Mix_123.php
│   ├── Mix_###.php
│   └── Mix_980.php
├── . . . 
└── Dir9

composer.json内容:

{
  "require": {
    "slim/slim": "2.6.2",
    "php": ">=5.4.0"
  },
  "autoload": {
    "psr-0": {
      "API": "src/"
    }
  },  
  "minimum-stability": "stable",
  "prefer-stable": true
}

我的系统规格是:

B$ cat /etc/centos-release
CentOS release 6.6 (Final)

B$ php -v
PHP 5.5.32 (cli) (built: Feb  2 2016 16:21:18)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2015 Zend Technologies
    with Xdebug v2.3.3, Copyright (c) 2002-2015, by Derick Rethans

【问题讨论】:

  • 你包含了 composer 的自动加载器吗?
  • 所以,您可以创建Mix 的实例,但即使$mix = new \API\Recipes\Mix_980(); 也不起作用?我们可以看看你的composer.json吗?
  • ls -l src/API/Recipes 的输出是什么?
  • 我在这里没有发现任何问题 - 出于调试目的,您可以使用 var_dump(spl_autoload_functions()); 代替 $mix = new \API\Recipes\Mix_980(); 吗?

标签: php class oop dynamic


【解决方案1】:

改变这一行:

$class = 'API\Recipes\Mix_' . $dynamic_id;

有了这个:

$class = '\API\Recipes\Mix_' . $dynamic_id;

顺便说一句,我注意到了;这也可能是错误的:

<?php

namespace API\Recipe;

use API\Recipes\Mix_980;

class Mix implements MixInterface

正确方法:

<?php

namespace API\Recipes;

use API\Recipes\Mix_980;

class Mix implements MixInterface

【讨论】:

  • 我尝试在发布前使用您的第一个提示,即添加具有相同结果的前导斜杠。第二个技巧中的命名空间建议并没有错,我特意将它们设置在不同的命名空间中。
  • @laygo 你确定将你的第二个代码块包含在你调用动态类的第一个代码中吗?
  • @laygo 我的意思是在这行代码之前$dynamic_id = 980; 你是不是写了include 'Mix_980.php';之类的东西
  • 自动加载不需要手动包含文件。这些文件已正确自动加载,我收到错误的原因是我的文件名没有完全像类名一样命名,这是 PSR-4 的要求。我没有意识到这一点。我的东西现在正在工作,因为我已经弄清楚了。 @Federico 昨天帮助我让它工作,但几分钟前我才意识到文件名。
  • 我只是在等待@Federico 发布我可以接受的答案。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 2015-01-12
  • 1970-01-01
  • 2011-04-04
  • 2014-09-27
相关资源
最近更新 更多