Я хочу быть в состоянии 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`"); } }
Где, как я реализую черты в зависимости от потребностей моих различных объектов. Подключение к базе данных, отладка отчетов и т. Д.
Ваш вопрос забавный, и 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 (), но это забавно, когда он решает проблему, которая иначе не может быть традиционно решена.
Легко!
Черта, которая может быть доступна или нет, будет либо использоваться, либо нет, но в конечном итоге поможет реализовать интерфейс:
<?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
реализовать общий интерфейс — в конце концов, вы, вероятно, захотите предоставить некоторую функциональность, которая будет разделена между двумя реализациями: одна использует черту, другая другими средствами (методы, предоставляемые этим классом).
Для справки смотрите:
Например, смотрите:
Вот чем я закончил:
eval("class myClass {". (trait_exists('myTrait') ? "use myTrait;" : "")
. str_replace(['class ', '<?php'], '//', file_get_contents(myClass.php"))
);
Полная лень:
trait_exists
линия, чтобы добавить больше чертclass
Ключевое слово и <?php
тег, так что вам не нужно редактировать файл классаЭто работает просто отлично для меня и «как есть» без каких-либо изменений в каком-либо файле, кроме того, в который я вставляю эту строку. Это, вероятно, не будет иметь место для вас.
Учтите тот факт, что:
Спасибо lacalheinz за его поучительный пост, но Стивен нацелился на буллиты с помощью eval ().