【问题标题】:Laravel 4: load class dynamically from string in databaseLaravel 4:从数据库中的字符串动态加载类
【发布时间】:2013-06-20 10:12:20
【问题描述】:

我希望我知道如何更恰当地搜索这个问题/短语。这妨碍了我寻找先前的问题;如果这是重复的,请耐心等待。

在这篇文章的底部查看更新/编辑

背景/我想做的事:

我有一个看起来很像这样的 URL:

http://myapp.com/calculate/$fileID/$calculateID

$fileID$calculateID 是我用来跟踪数据集的键,我称之为“计算”。本质上,该 URL 表示对 $fileID 中的数据执行 $calculateID

我去我的数据库 (mongo) 并询问一个 php 类名或 sring 或文件路径,或者你有什么匹配 $calculateID。例如,假设表格如下所示:

 +-----+-------------------+
 | _id |     phpFile       |
 +-----+-------------------+
 |   1 | basicCalcs.php    |
 |   2 | advancedCalcs.php |
 |   3 | summaryCalcs.php  |
 +-----+-------------------+

注意:可以安全地假设phpFile 列中的每个文件都有一个公共接口/一组公共方法。

示例:

http://myapp.com/calculate/23/2

会去数据库,从集合23获取数据,然后加载advancedCalcs.php中的函数。一旦advancedCalcs.php 被加载,其中的一个函数将接收数据。从那里,对数据执行一组计算和转换。

我的问题

我的问题是动态加载advancedCalcs.php 并将数据输入一组方法的“laravel 4 友好”方式是什么?有没有办法延迟加载这种类型的东西。目前,我只知道非常简单的require_once() 方法。我真的很想避免这种情况,因为我确信 laravel 4 具有动态加载底层类并将其连接到通用接口的功能。

编辑 1

感谢 Antonio Carlos Ribeiro,我得以取得一些进展。

运行 dump-autoload 命令后,我的 vendor/composer/autoload_classmap.php 文件有几个新条目,如下所示:

'AnalyzeController' => $baseDir . '/app/controllers/AnalyzeController.php',
'AppName\\Calc\\CalcInterface' => $baseDir . '/app/calculators/CalcInterface.php',
'AppName\\Calc\\basicCalcs' => $baseDir . '/app/calculators/basicCalcs.php',

使用下面示例的代码,我可以创建 basicCalcs 类的实例:

$className = "AppName\\Calc\\basicCalcs";

$instance = new $className; 

var_dump($instance);

basicCalcs.php 文件如下所示:

//PATH: /app/calculators/basicCalcs.php
<?php namespace Reporter\Calc;


class basicCalcs {


    public function sayHi(){
        echo("hello world! i am basicCalcs");
    }

};

?>

更新问题: 如何在autoload_classmap.php 中创建类似于AnalyzeController 条目的别名,而不必使用完整的命名空间引用basicCalcs.php

【问题讨论】:

    标签: php class dynamic laravel laravel-4


    【解决方案1】:

    将你的库文件夹添加到你的 composer.json 自动加载中:

    "autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/extended",
            "app/calculators",  <------- This is where you put all your calculators
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php"
        ]
    },
    

    更新您的自动加载的类:

    composer dump-autoload
    

    如果您想确保它确实有效,请检查您的类是否在打开文件时自动加载

    vendor/composer/autoload_classmap.php
    

    要动态地实例化它们,最好将其作为表类名:

    +-----+-------------------+-------------------+
    | _id |     phpFile       |  namespace        |
    +-----+-------------------+-------------------+
    |   1 | basicCalcs        | Reporter\Calc\    |
    |   2 | advancedCalcs     | Reporter\Calc\    |
    |   3 | summaryCalcs      | Reporter\Calc\    |
    +-----+-------------------+-------------------+
    

    那么你只需要使用它

    class CalculateController extends Controller {
    
        public function calculate($fileID, $calculateID)
        {
            $file = phpFile::find($fileID);
    
            $className = $file->namespace . $file->phpFile;
    
            $calculator = new $className; //// <--- this thing will be autoloaded
    
            return $calculator->calculate( $calculateID );
        }
    
    }
    

    我假设你的计算器都是:

    class basicCalcs {
    
        public function calculate($calculateID)
        {
            return performCalculation( $calculateID ); /// something like this
        }
    
    }
    

    你的路由器有点像

    Route::get('/calculate/{fileID}/{calculateID}', array('as'=>'calculate', 'uses'=>'CalculateController@calculate'));
    

    【讨论】:

    • 谢谢。我知道您正在尝试做什么,但是 laravel 4 的 Filesystem 类中不存在 find() 方法。我似乎也无法在 php.net 上找到太多提及它的内容。通过这样做$className = "The\\Namespace\\path\\Inautoload_classmap.php"; $instance = new $className; 有效,我能够得到我需要的东西,但是有什么方法可以为命名空间设置别名吗?
    • 对不起那个 File::,我把它改成 phpFile 是为了更清楚,因为它应该是你的 phpFile 模型,你存储文件名的地方。只要你的类出现在 autoload_classmap.php 文件中,你就不需要命名空间,除非你需要它们来组织你的代码,当然。
    • namespace 如果你想使用psr0 是必需的。
    • 啊,安东尼奥,我现在明白了。我的类出现在自动加载文件中,但仅限于命名空间。我已经更新了我的原始帖子以反映这一点。我可以通过使用它的完整命名空间来引用它来加载该类,所以我最终可能只是将它存储在数据库中
    • 我认为你有两个选择:添加命名空间 '$class = 'Reporter\Calc\' . $file->phpFile; 中引用它。刚刚编辑以支持您的命名空间。
    【解决方案2】:

    Laravel4 中的文件composer.json 负责这个,下面是一个例子

    {
        "require": {
            "laravel/framework": "4.0.*"
        },
        "autoload": {
            "classmap": [
                "app/commands",
                "app/controllers",
                "app/models",
                "app/database/migrations",
                "app/database/seeds",
                "app/tests/TestCase.php"
            ]
        },
        "scripts": {
            "post-update-cmd": "php artisan optimize"
        },
        "config": {
            "preferred-install": "dist"
        },
        "minimum-stability": "dev"
    }
    

    注意autoload 部分,其中classmap 用于告诉laravel4 它应该从哪些文件夹加载类以及它应该加载哪个文件。例如,"app/controllers", 将用于从 app/controllers 文件夹加载所有类,"app/tests/TestCase.php" 将使 Laravel4app/tests/ 文件夹自动加载类 TestCase.php。因此,将您的库文件夹添加到 classmap 部分。在autoload -&gt; classmap 部分中添加文件夹路径后,您必须运行

    composer dumpautoload // or
    composer dump-autoload
    

    从命令行。

    【讨论】:

    • 谢谢;这让我朝着正确的方向前进。我的原始问题已更新,以反映我现在遇到的问题。
    猜你喜欢
    • 2014-12-11
    • 2017-12-21
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多