11

Consider the situation where there are multiple classes that all need to have access to the configuration storage mechanism, but cannot be extended from a base class because of the architectuur of the framework. In addition to that I wanted to keep the storage mechanism flexible (be able to switch storage backend later).

I felt it would make sense to create a trait which does the actual saving and use those functions inside all classes (for the example I use $_SESSION as storage system):

trait MyTrait {

  function setting_enabled() {
    return !empty($_SESSION['setting']) ? TRUE : FALSE;
  }

  function enable_setting() {
    $_SESSION['setting'] = TRUE;
  }

  function disable_setting() {
    $_SESSION['setting'] = FALSE;
  }

}

This works great from classes. There is however also one file that is not a class, but is just plain PHP, for which I also need to know if the setting is enabled.

I have tried declaring the function as static:

trait MyTrait {

  static function setting_enabled() { // Declared as static function
    return !empty($_SESSION['setting']) ? TRUE : FALSE;
  }

  ...
}

And then call the static function from the trait, which worked fine.

if (MyTrait::setting_enabled()) {
  ...
}

It however feels not entirely right. On the other hand, creating a new empty class that uses the trait and instantiating that to obtain the value seems like a lot of overhead.

Am I allowed to do this (as of PHP 5.6, but also considering the future with PHP 7.x)?

3 Answers 3

21

PHP does not allow calling trait's methods without some class (no matter if static or not).

A simple workaround is to use an anonymous class mediately:


...

(new class { use MyTrait; })::myMethod();

...

I like this way a little bit more because we don't create an unnecessary class name.

Sign up to request clarification or add additional context in comments.

3 Comments

Apparently calling static methods from traits works: 3v4l.org/uQfuK although it's deprecated in 8.1 (and rightly so)
Nice workaround, still feels hacky tough.
In case if the static call is deprecated, just add a proxy method into the anonymous class and then call it the same way.
9

If you have a trait then you decided to make a multiple inheritance once, maybe for multiple classes. Otherwise, it's redundant declaration and you have to use a class. In fact, and existing of trait means its using.

If you have a static function inside trait, then why you can't using its from the class you'd implemented trait in?

trait MyTrait {
 static myFunc() {}
}

class ThatUsingMyTrait {
 use MyTrait;
}

// pretend below a code where you want to use the trait.
if(ThatUsingMyTrait::myFunc()) {
 // do something
}

The code also is may be a class you want to implement without trait directly.

Hope I describe the idea understandingly.

4 Comments

It works very well in classes. And I could indeed instantiate a class that uses the trait. The actual question is if I am allowed to use MyTrait::setting_enabled() outside of a class. It works, but I could not find any documentation on whether this is a bug or a feature.
I think it isn't a bug. The definition on the php.net sound as "A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way." You can't instantiate a trait, but since it's similar to class in all other features the trait should be process all other actions on itself. And once again, the corner idea, if you can copy and paste the code from one class to another then you have a candidate for trait.
Thanks, I suppose it is save to use then.
This is detailed explanation. Works with php 8.1.
0

unsure to import your trait be truing to resolve it: In case of non-static method

(new class { use MyTrait; })->myMethod();

but it seem it deprecated on php 8

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.