在自定义类/子系统中使用Laravel 4模型而不依赖于类

时间:2014-01-09 17:11:52

标签: php xml parsing laravel laravel-4

我正在构建一个解析器系统,它将根据request / cronjob解析大量不同的XML / JSON提要。 我使用Laravel 4。

该主题的目的是在我的上下文中使用IoC,而不是在自定义类方法中使用硬编码的模型名称

为具有XML结构的Soccer Player提供解析器示例,如:

<players category="Midfielders">
   <player id="777">
      <name>Caio Augusto Paim do Santos</name>
   <statistic>
      <club name="Camaçari" id="7191" league="Baiano 2" league_id="1136" season="2013" minutes="" appearences="" lineups="" substitute_in="" substitute_out="" substitutes_on_bench="" goals="" yellowcards="" yellowred="" redcards=""/>

我在/ app文件夹中创建了一个名为/ parsers的附加目录这些是自定义类,它们都在同一文件夹中扩展或实现自定义摘要/接口,基本上负责接收XML / JSON文件的路径并返回结构良好的PHP数组。

它们在autoload的composer.json中添加为:"app/parsers"

附加文件结构的屏幕截图enter image description here

一切都很好,代码/类是可测试的,不依赖于另一个类,但这就是问题所在。

签出XML示例,有类似的事情: <club id="XXX" league_id="YYY" />  这是饲料俱乐部ID和饲料联盟ID,但我在数据库中有自己的ID参考饲料ID。

喜欢这个截图:

enter image description here

所以逻辑说:转到数据库,检查联盟列表中是否有来自XML文件提供的feed_id的id。 如果是,请获取它,如果没有,请创建一个新的联盟并获取未来参考的ID。

这需要我在我的解析器类中使用Model,现在我知道你可以使用IoC并将模型注入到控制器中,但我不确定我是否可以对我的解析器类做同样的事情......

在我的解析器类中间执行类似的操作:

// Try to get league and season ids from database if they already exists, if not, insert
$leagueId = DB::select('SELECT id FROM league WHERE feed_id=?', array($data['league_id']));

$league = new LeagueModel();

非常不正确。

现在只是为了澄清它的工作方式,我的解析器会在Laravel Command类中被调用,如下所示:

/**
* Execute the console command.
*
* @return void
*/
public function fire()
{
    $this->setParser();
    $this->setStorage();
    $this->parser->parseFile($file);
}

Laravel Command类在我的控制器中被调用,如:

$stamps = $this->getStamp();
Artisan::call('command:getSoccerPlayer',array('stamps' => $stamps, 'parser_id' => Request::segment(2)));

Controller本身通过URI调用: /jobs/soccer_player/parse?type=soccer&directory=players

**您有什么建议或者您将如何克服此问题以避免依赖性,并仍然使用模型在此上下文中与数据库进行交互? **

PS请不要注意我的屏幕截图上的整个解析逻辑现在使用相同的方法“解析”,一旦我看到我想要它的工作/外观的全貌,我会将其分解成碎片。

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

您仍然可以调用命名空间模型

use App\Models\League; 

class SoccerPlayerParser extends AbstractParser{
    //...

    public function parse()
    {
       //...
        $league = App\Models\League::find($data['league_id']);
       //...
    }

    //....
}

答案 1 :(得分:1)

我在这里看到两种可能的解决方案,但我不能100%确定如何将它集成到您​​的项目中。

第一种方法是存储要在配置文件中使用的模型类的名称,并通过new $class对模型进行实例化,其中$ class是通过Config::get或类似方法检索的值。这个解决方案在包中很常见,甚至Laravel本身也使用它(参见app / config / auth.php中的模型设置)。

另一个是不实例化模型,而是为它创建一个接口,然后依赖注入它到你的命令中。您可以使用Artisan::resolve('MyNamespace\MyCommand')而不是Artisan::add(new MyCommand)轻松地将内容自动注入到命令中,然后通过类型提示注入,就像通过控制器一样。 http://laravel.com/docs/ioc#practical-usage

一旦将接口设置为命令构造函数的参数,就可以使用App::bind('MyInterface', 'MyModel')告诉Laravel要注入哪个类,这可以在任何时候交换。