Php 要求我的Laravel 4套餐为“1”是一种良好的做法吗;“扩展”;用户为了使用它?

Php 要求我的Laravel 4套餐为“1”是一种良好的做法吗;“扩展”;用户为了使用它?,php,laravel,laravel-4,package,extends,Php,Laravel,Laravel 4,Package,Extends,我可以想出两种方法来创建一个Laravel 4包,以实现我的目标: 要求软件包用户扩展它: // YourCoolService.php class YourCoolService extends MyCoolPackage { // add the appropiate properties & methods // that MyCoolPackage will expect to use } // YourCoolService.php clas

我可以想出两种方法来创建一个Laravel 4包,以实现我的目标:

要求软件包用户扩展它:

// YourCoolService.php

class YourCoolService extends MyCoolPackage {

      // add the appropiate properties & methods 
      // that MyCoolPackage will expect to use

}
// YourCoolService.php

class YourCoolService {   // <-- no extending here

      // add the appropiate properties & methods 
      // that MyCoolPackage will expect to use

}    


或将类名作为字符串参数传递到我的包中:

// YourCoolService.php

class YourCoolService extends MyCoolPackage {

      // add the appropiate properties & methods 
      // that MyCoolPackage will expect to use

}
// YourCoolService.php

class YourCoolService {   // <-- no extending here

      // add the appropiate properties & methods 
      // that MyCoolPackage will expect to use

}    

“扩展”解决方案
专业的

  • 来自控制器的调用更精简
  • 我不必在控制器中的调用上直接使用名称空间
  • 我可以创建抽象方法来通知用户他们需要实现它们(尽管这也可以通过接口实现)
犯人

  • 用户无法扩展任何其他类,因为他们正在扩展MyColPackage
  • 如果我想在MyColPackage中有一些“helper”函数,那么调用类似于
    parent::helper()将出现在整个YourCoolService类中(但我想我仍然可以像
    MyColPackage::helper();
    那样调用它)
“传递类名”解决方案
专业的

  • 用户不必扩展任何内容
  • 从控制器中的调用可以明显看出正在使用什么包
  • 如果我想在mycolpackage中有一些“helper”函数,那么我可以像调用
    mycolpackage::helper('foo')那样调用它们CoolService类中的任何位置,它们的来源都是显而易见的
犯人

  • 控制器中的调用较长
  • 我可能需要为MyColPackage创建一个接口供您的CoolService使用(尽管我认为这不是绝对必要的)
  • 控制器中的调用需要在传递的字符串中包含完整的命名空间(是否有办法避免在字符串中包含命名空间?

创建要求属性和方法存在于用户自己的类实现中的包的最佳实践是什么?

我的意见是最好使用,鉴于Laravel提供的DI功能,您可以允许包的用户在对象的构造函数中插入对
mycolpackage
实例的引用。然后,您的
make
方法就不必静态调用(如果是这样的话,也可以通过facade调用)

其基本思想是,每当包的用户创建一个新服务时,该服务类都应该向包中注入一个实例

<?php namespace Namespace;

use MyCoolPackage\MyCoolPackage;

class YourCoolService {

    protected $myCoolPackage;

    public function __construct( MyCoolPackage $package )
    {
        $this->myCoolPackage = $package;
    }

    ...

$this->myCoolPackage->make('Namespace\YourCoolController')
    ->withInput(Input::all())->render();
要提供DI功能,您需要创建一个服务提供商,以便在构造函数中提示类型为
MyCoolPackage\MyCoolPackage
时,在IoC中绑定
MyCoolPackage
的实例。请参阅:

由于您将离开
YourCoolService
由其他人在其他地方定义,因此除了为编写服务的人员提供某种范例之外,您别无选择。如果您可以为他们提供一个要实现的接口,那将是最好的情况,因为它将为编写这些服务的人员提供一个模板

您还可以提供一个抽象基类,它将为用户提供所有其他实现都可以选择覆盖或不覆盖的任何可选方法的默认实现。这种方法将类似于您的“扩展”方法,并为您提供一些相同的pro


我从来都不喜欢将类名作为字符串传递。我打赌它有一些使用案例,但对我来说,它只是一种隐含的依赖性,而你并不真正需要它。

根据watcher的回答,我最终做了如下事情:

// YourCoolService.php

class YourCoolService implements MyCoolPackageInterface {

    public function makeCool(MyCoolPackage $myCoolPackage)
    {
        return $myCoolPackage->make($this);
    }

}


// YourController.php

$output = (new YourService)->makeCool()->withInput(Input::all())->render(); 

...   

具有美观的调用控制器的优点,并且不受继承。太好了

您能在回答中详细说明如何从控制器调用它吗?如下调用:
$output=YourCoolService::mycolpackage::make()->withInput(Input::all())->render()???不。如果你真的想在客户端服务上使用静态方法,你必须用不同的方法,但我不建议你这么做。如果我不“静态”使用它,你会如何从控制器调用它?这一行
$This->mycolpackage->make('Namespace\YourCoolController')->withInput(Input::all())->render();对我来说没有意义?您正在从您的服务呼叫控制器?我遗漏了什么吗?您没有在那里使用
static
。替换为
self
重新运行测试,您将看到应用程序的行为完全相同。这与后期静态绑定无关(如果在控制器脚本中没有使用类别名的话)。我只想使用
static
,以防以后扩展此类。YourCoolService是由软件包的用户提供的……他们可能会决定创建BaseCoolService或其他东西,并从YourCoolService进行扩展。那么
self
就不再正确了?我没有检查
$instance
是否已经存在,就像我在许多单例实现中看到的那样。我为什么要这么做?
// YourCoolService.php

class YourCoolService implements MyCoolPackageInterface {

    public function makeCool(MyCoolPackage $myCoolPackage)
    {
        return $myCoolPackage->make($this);
    }

}


// YourController.php

$output = (new YourService)->makeCool()->withInput(Input::all())->render(); 

...