我希望能够use
特性如果可用。
显然我不能在类本身内部定义(语法错误)
//fails
include_once('myTrait.php');
class foo
{
var $bar;
if (trait_exists('myTrait')) {
use myTrait;
}
}
//also fails
foo use myTrait;
//also fails
$f = new foo();
$f use myTrait;
//also fails
$f = new foo() use myTrait;
理想的案例场景将是这样的:
class foo
{
var $bar;
}
if (file_exists('myTrait.php')) {
include_once('myTrait.php');
//make class foo use myTrait;
}
$f=new foo();
很难找到文档和特征似乎不太受欢迎,但在我的特定情况下,它们非常有用。我还尝试通过仅在需要时包含文件来保持资源尽可能低。
提示,文件和解释一如既往地欢迎。
我的搜索最接近我的是http://brendan-bates.com/traits-the-right-way/
让我们说一些控制器(但不是全部)需要一个 数据库连接。为了保持提升,我们不应该给每一个人 控制器数据库连接。我们能做的就是写一个 扩展BaseController的抽象类,它提供了一个数据库 连接。但是,在将来,如果一个对象不是一个 控制器需要数据库连接?而不是重复这个 逻辑,我们可以使用水平重用。
可以创建一个简单的特征:
trait DatabaseAware { protected $db; public function setDatabase($db) { $this->db = $db; } protected function query($query) { $this->db->query($query); } }
此特征现在提供具有通用数据库功能的类。 任何需要数据库连接的类,无论是控制器还是 经理(或任何事情),可以使用这个特性:
class IndexController extends BaseController { use DatabaseAware; public function indexAction() { $this->query("SELECT * FROM `someTable`"); } }
我根据不同对象的需要实现特征。数据库连接,调试报告等
答案 0 :(得分:4)
容易!
可能使用与否的特性将被使用或不使用,但最终将有助于实现接口:
<?php
trait BarTrait
{
public function bar()
{
return 'Hey, I am your friend!';
}
}
我们希望实现的界面:
<?php
interface BarInterface
{
/**
* @return string
*/
public function bar();
}
使用特征FooUsingBarTrait
实现上述接口的类BarTrait
:
<?php
class FooUsingBarTrait implements BarInterface
{
use BarTrait;
}
类FooNotUsingBarTrait
,它不使用特征BarTrait
,而是实现上述接口本身:
class FooNotUsingBarTrait implements BarInterface
{
public function bar()
{
return 'Hey, I am one of your friends!';
}
}
最后,有条件地定义一个类Foo
,具体取决于是否存在特征BarTrait
:
<?php
if (trait_exists(BarTrait::class) {
class Foo extends FooUsingBarTrait
{
}
} else {
class Foo extends FooNotUsingBarTrait
{
}
}
$foo = new Foo();
$foo->bar();
var_dump(
get_class($foo),
class_parents(Foo::class)
);
注意如果类FooUsingBarTrait
和FooNotUsingBarTrait
都实现了一个公共接口,这可能是最有意义的 - 毕竟,您可能希望提供一些将在这两个实现:一个使用特征,另一个使用其他方法(该类提供的方法)。
供参考,见:
例如,请参阅:
答案 1 :(得分:0)
您的问题很有趣,而eval()可能会满足您的需求。使用代码生成的这种风格很难看,但我知道它有效,因为我在自己的机器上验证了它。这是你如何做到的:
$src = '
class foo {
var $bar; // and all of your other code goes here
';
if (file_exists('myTrait.php')) {
include_once('myTrait.php');
$src .= "use myTrait;\n";
}
$src .= "}";
eval ($src); // your class finally gets declared
我不经常使用eval(),但它解决了传统上无法解决的问题时很有趣。
答案 2 :(得分:-1)
这里我最终得到了:
eval("class myClass {"
. (trait_exists('myTrait') ? "use myTrait;" : "")
. str_replace(['class ', '<?php'], '//', file_get_contents(myClass.php"))
);
总懒惰:
trait_exists
行以添加更多特征class
关键字和<?php
代码,这样您就不必编辑类文件这对我来说很好 和'原样'没有对任何文件进行任何修改,除了我粘贴这一行的文件。你可能不会这样。
考虑以下事实:
感谢lacalheinz的指导性帖子,但史蒂文瞄准了带有eval()的窃贼。