Php 如果存在一个trait,我如何有条件地让类使用它?
我希望能够Php 如果存在一个trait,我如何有条件地让类使用它?,php,traits,Php,Traits,我希望能够使用特性(如果可用) 显然,我不能在类本身内部定义它(语法错误) 理想情况是这样的: class foo { var $bar; } if (file_exists('myTrait.php')) { include_once('myTrait.php'); //make class foo use myTrait; } $f=new foo(); 很难找到文档和特性似乎并不流行,但在我的特殊情况下,它们非常有用。我还试图通过仅在需要时包含文件来尽可能地减少资
使用特性(如果可用)
显然,我不能在类本身内部定义它(语法错误)
理想情况是这样的:
class foo
{
var $bar;
}
if (file_exists('myTrait.php')) {
include_once('myTrait.php');
//make class foo use myTrait;
}
$f=new foo();
很难找到文档和特性似乎并不流行,但在我的特殊情况下,它们非常有用。我还试图通过仅在需要时包含文件来尽可能地减少资源
如往常一样,欢迎提供提示、文档和解释
我的搜索给我带来的最接近的东西是这篇文章
假设其中一些控制器(但不是全部)需要
数据库连接。为了保持业绩,我们不应该放弃每一个机会
控制数据库连接。我们能做的就是写一个
扩展提供数据库的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`");
}
}
当我根据不同对象的需求实现特征时。数据库连接、调试报告等。简单
特质
一个特性可能可用或不可用,将被使用或不使用,但最终将有助于实现接口:
<?php
trait BarTrait
{
public function bar()
{
return 'Hey, I am your friend!';
}
}
<?php
class FooUsingBarTrait implements BarInterface
{
use BarTrait;
}
类不使用trait
一个类footusingbartrait
,它不使用traitBarTrait
,而是实现上述接口本身:
class FooNotUsingBarTrait implements BarInterface
{
public function bar()
{
return 'Hey, I am one of your friends!';
}
}
有条件地创建类定义
最后,根据traitBarTrait
是否存在,有条件地定义一个类Foo
:
<?php
if (trait_exists(BarTrait::class) {
class Foo extends FooUsingBarTrait
{
}
} else {
class Foo extends FooNotUsingBarTrait
{
}
}
注意如果两个类fooousingbartrait
和fooonotusingbartrait
都实现了一个公共接口,那么这可能是最有意义的——毕竟,您可能希望提供一些在两个实现之间共享的功能:一个使用特征,另一个通过其他方式(该类提供的方法)
有关参考,请参阅:
有关示例,请参见:
您的问题很有趣,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(),但当它解决了一个传统方法无法解决的问题时,它会很有趣。以下是我的结论:
eval("class myClass {"
. (trait_exists('myTrait') ? "use myTrait;" : "")
. str_replace(['class ', '<?php'], '//', file_get_contents(myClass.php"))
);
eval(“类myClass{”
(trait_存在('myTrait')?“使用myTrait;”:“”)
.str_replace(['class','您可以根据trait的存在定义一个完整的类(如果trait_存在('myTrait'))
)一个trait
“增强”一个有新方法的类。如果你不知道在什么时候编写代码时类是否提供了这些方法,你打算如何使用这些方法?在我看来,你试图以错误的方式解决一个完全不同的问题。“我还试图通过只在需要时包含文件来尽可能减少资源。”--这是自动加载程序的责任。@axiac这可以通过实现接口来解决-要么trait提供了实现,要么就实现了。trait不是动态功能。它要么存在,要么就不存在。如果它不存在,那么使用的类也不存在;它们无法加载如果特征存在,那么整个问题就没有任何意义。在你需要的地方使用它,不要费心检查它的存在。如果你需要一个可能可用或不可用的功能(因为外部原因,而不是因为代码不存在)然后,解决方案使用了其他技术:和设计模式。很多文档都谈到了与traits一起使用的界面。我将在界面文档中挖掘更多内容。你的大部分答案都是我已经知道但从另一个角度来看的。呵呵,很高兴为你服务-希望解决方案对你有效,@LouisLoudogTrottier!我猜是这样的$src可以是任何解释为字符串的东西?ob_start();包括'src/class.php';$src=ob_get_contents();…
我的问题可能很有趣,但我会更有趣地尝试这个问题,并调整它以适应我的懒散。这没什么大不了的,但我肯定会尝试一下,因为这似乎是最接近我所寻找的解决方案。谢谢你,有点吹毛求疵,我能够将其混合到一行中。而且,现在真正的乐趣开始了,我知道如何利用它以及何时不使用它。我很高兴它对你有用!看起来你在我建议的答案上有所改进。根据你的评论,我很确定我知道你做了什么,我认为这很好!
$foo = new Foo();
$foo->bar();
var_dump(
get_class($foo),
class_parents(Foo::class)
);
$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("class myClass {"
. (trait_exists('myTrait') ? "use myTrait;" : "")
. str_replace(['class ', '<?php'], '//', file_get_contents(myClass.php"))
);