如果可用,我希望能够使用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;
Run Code Online (Sandbox Code Playgroud)
理想的情况是这样的:
class foo
{
var $bar;
}
if (file_exists('myTrait.php')) {
include_once('myTrait.php');
//make class foo use myTrait;
}
$f=new foo();
Run Code Online (Sandbox Code Playgroud)
很难找到文档和特征似乎不是很受欢迎,但在我的特殊情况下,它们非常有用。我还尝试通过仅在需要时包含文件来尽可能降低资源。
像往常一样欢迎提示、文档和解释。
我的搜索带给我的最接近的是这篇文章http://brendan-bates.com/traits-the-right-way/
假设其中一些控制器(但不是全部)需要数据库连接。为了保持性能,我们不应该为每个控制器提供数据库连接。我们可以做的是编写一个抽象类,它扩展了提供数据库连接的 BaseController。但是,将来,如果不是控制器的对象需要数据库连接怎么办?我们可以使用水平重用,而不是复制这个逻辑。
可以创建一个简单的特征:
Run Code Online (Sandbox Code Playgroud)trait DatabaseAware { protected $db; public function setDatabase($db) { $this->db = $db; } protected function query($query) { $this->db->query($query); } }此特征现在提供具有通用数据库功能的类。任何需要数据库连接的类,无论是控制器还是管理器(或任何东西),都可以使用这个特性:
Run Code Online (Sandbox Code Playgroud)class IndexController extends BaseController { use DatabaseAware; public function indexAction() { $this->query("SELECT * FROM `someTable`"); } }
当我根据不同对象的需要实现特征时。数据库连接、调试报告等。
简单!
一个可能可用或不可用的特征,将被使用或不被使用,但最终将有助于实现一个接口:
<?php
trait BarTrait
{
public function bar()
{
return 'Hey, I am your friend!';
}
}
Run Code Online (Sandbox Code Playgroud)
我们希望实现的接口:
<?php
interface BarInterface
{
/**
* @return string
*/
public function bar();
}
Run Code Online (Sandbox Code Playgroud)
一个FooUsingBarTrait使用 traitBarTrait来实现上述接口的类:
<?php
class FooUsingBarTrait implements BarInterface
{
use BarTrait;
}
Run Code Online (Sandbox Code Playgroud)
一个FooNotUsingBarTrait不使用 trait BarTrait,而是实现上述接口本身的类:
class FooNotUsingBarTrait implements BarInterface
{
public function bar()
{
return 'Hey, I am one of your friends!';
}
}
Run Code Online (Sandbox Code Playgroud)
最后,Foo根据特征是否BarTrait存在,有条件地定义一个类:
<?php
if (trait_exists(BarTrait::class) {
class Foo extends FooUsingBarTrait
{
}
} else {
class Foo extends FooNotUsingBarTrait
{
}
}
Run Code Online (Sandbox Code Playgroud)
$foo = new Foo();
$foo->bar();
var_dump(
get_class($foo),
class_parents(Foo::class)
);
Run Code Online (Sandbox Code Playgroud)
注意这可能更有意义,如果两个类FooUsingBarTrait和FooNotUsingBarTrait实现共同的接口-毕竟,你可能想提供一些功能,这将在两个实现之间可以共享:使用特点,通过该类提供的其他方式(方法中的一种,其他)。
参考:
有关示例,请参阅:
你的问题很有趣,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
Run Code Online (Sandbox Code Playgroud)
我不经常使用 eval(),但是当它解决了传统方法无法解决的问题时,它很有趣。