Php method exists trait

PHP method_exists

Summary: in this tutorial, you’ll learn how to use the PHP method_exists() function to check if a class or an object of a class has a specified method.

Introduction to the PHP method_exists function

The method_exists() function returns true if an object or a class has a specified method. Otherwise, it returns false .

The syntax of the method_exists() function is as follows:

method_exists(object|string $object_or_class, string $method): boolCode language: PHP (php)

The method_exists() has two parameters:

  • $object_or_class is an object or a class in which you want to check if a method exists.
  • $method is a string that represents the method to check.

PHP method_exists function examples

Let’s take some examples of using the method_exists() function.

1) Using the PHP method_exists() function to check if a class has a method

The following example uses the method_exists() function to check if a method exists in the BankAccount class:

 class BankAccount < public function transferTo(BankAccount $other, float $amount) < // more code > > $exists = method_exists(BankAccount::class, 'transferTo'); var_dump($exists); // bool(true) $exists = method_exists(BankAccount::class, 'deposit'); var_dump($exists); // bool(false)Code language: PHP (php)

In this example, the following statement returns true because the transferTo method exists in the BankAccount class:

method_exists(BankAccount::class, 'transferTo');Code language: PHP (php)

However, the following statement returns false because the deposit method doesn’t exist in the BankAccount class:

method_exists(BankAccount::class, 'deposit');Code language: PHP (php)

2) Using the PHP method_exists function to check if an object has a method

The following example creates a new object of the BankAccount and uses the method_exists() function to check the object has a specified method:

 class BankAccount < public function transferTo(BankAccount $other, float $amount) < // more code > > $account = new BankAccount(); $exists = method_exists($account, 'transferTo'); var_dump($exists); // bool(true) $exists = method_exists($account, 'deposit'); var_dump($exists); // bool(false)Code language: PHP (php)

The $account object has the transferTo method, therefore, the following statement returns true :

method_exists($account, 'transferTo');Code language: PHP (php)

On the other hand, the $account object doesn’t have the deposit method. Therefore, the following statement returns false :

method_exists($account, 'deposit');Code language: PHP (php)

3) Using the method_exists function to check if an object has a static method

The method_exists() also returns true if a class has a static method. For example:

 class BankAccount < public function transferTo(BankAccount $other, float $amount) < // more code > public static function compare(BankAccount $other): bool < // implementation // . return false; > > $exists = method_exists(BankAccount::class, 'compare'); var_dump($exists); // bool(true) $account = new BankAccount(); $exists = method_exists($account, 'compare'); var_dump($exists); // bool(true)Code language: PHP (php)

The BankAccount has the compare static method, so the following statement returns true :

method_exists(BankAccount::class, 'compare');Code language: PHP (php)

The $account is an instance of the BankAccount class that has the compare static method, the following expression also returns true :

$exists = method_exists($account, 'compare');Code language: PHP (php)

PHP method_exists function in MVC frameworks

The method_exists() method is often used in Model-View-Controller (MVC) frameworks to check if a controller class has a certain method before calling it.

For example, suppose that you have the following request URI:

/posts/edit/1Code language: PHP (php)

This URI has three parts: posts, edit, and 1.

  • The posts maps to the PostsController class.
  • The edit maps the edit method of the class.
  • The number 1 is the post id to edit.

The PostsController class will look like the following:

 class PostsController < public function edit(int $id) < // show the edit post form > >Code language: PHP (php)

And you use the method_exists() function to check whether the edit method exists in the $controller object like this:

 // . if(method_exists($controller, $action)) < $controller->$action($id); >Code language: PHP (php)

Summary

Источник

trait_exists

Нужно ли автоматически подгружать класс, если он ещё не загружен.

Возвращаемые значения

Возвращает true , если трейт существует, в противном случае возвращает false .

User Contributed Notes 3 notes

private static $instance ;
protected $tmp ;

public static function World ()
self :: $instance = new static();
self :: $instance -> tmp = get_called_class (). ‘ ‘ . __TRAIT__ ;

public function text ( $str )
return $this -> tmp . $str ;
>
>

echo Hello :: World ()-> text ( ‘. ‘ ); // Hello World.

Traits are compatible with class autoload mechanism — in fact, if you look at source code of trait_exists function, you will find similar peace of code (see Zend/zend_builtin_functions.c)

What is the default value of $autoload? And in which way traits are autoloaded? Is there something as spl_autoload() for traits?

  • Функции работы с классами и объектами
    • class_​alias
    • class_​exists
    • enum_​exists
    • get_​called_​class
    • get_​class_​methods
    • get_​class_​vars
    • get_​class
    • get_​declared_​classes
    • get_​declared_​interfaces
    • get_​declared_​traits
    • get_​mangled_​object_​vars
    • get_​object_​vars
    • get_​parent_​class
    • interface_​exists
    • is_​a
    • is_​subclass_​of
    • method_​exists
    • property_​exists
    • trait_​exists
    • _​_​autoload

    Источник

    Conclusion:

    Traits are, all in all, a missed opportunity IMO. They could’ve been a sensible feature to reduce code duplication, if they’d kept the number of “features” down. But they didn’t, they tried to implement traits as an optional, partial, abstract contract so what you end up with is a feature that is neither here nor there. In true PHP style, the way you use it is your own responsibility or, if you’re going trait crazy, your own problem.

    There are a number of blog-posts out there telling you how fantastic traits are, and what you can use them for. I’ve yet to find a single one that actually warns about the pitfalls that they bring to the party. Seeing as PHP is a language that is very accessible, there are a lot of people out there writing a lot of code that isn’t really representative of what PHP can do in the right hands. I fear that traits, as they are implemented at the moment, are going to be hugely popular with people who might not be fully aware of the very sensible, simple, but vital SOLID principles.
    There is a real chance for traits to become the next eval: the first resort people will use to solve issues that should’ve never have existed in the first place.

    If you’ve read through this gibberish, and if you were to take anything from this rant, let it be this:

    Use traits if you want to, but use them to reduce code duplication only. Don’t try to enforce contracts with them: they’re just not capable. Steer well clear of the more complex “features” like the aliasing and the insteadof keyword. And do your absolute best to avoid using multiple traits. Traits are weak contracts, to avoid the diamond problem, usign multiple weak contracts reintroduces that same diamond problem, which is what insteadof and as are meant to solve, but really: they’re moving the problem instead of fixing it. Ironically, 9/10 times, if you really look at your code, using a trait is merely moving the problem, too: if you write your code well (following what I believe to be the most important of the SOLID principles: Single responsability), single inheritance really is enough.

    Don’t take my word for it, many people who are well versed in C++ (which does support multiple inheritance) will tell you multiple inheritance is not needed, and generally a bad idea. Even the person who created C++ (Bjarne Stroustrup) said as much:

    “People quite correctly say that you don’t need multiple inheritance, because anything you can do with multiple inheritance you can also do with single inheritance. You just use the delegation trick I mentioned.”

    An alternative to traits?

    Is there an alternative – Yes, of course there is. As the quote above states: you can use the delegation trick (using DI). Let’s take the Optimist trait example we used earlier, and see how we can implement that functionality without traits:

    //first, create a base for traits, an abstract class abstract class Trait < protected $name = ''; protected $users = []; final public function getName() < return $this->name; > final public function registerUser($usedBy) < $this->users[] = $usedBy;//this is not the optimal way, use an assoc array if possible, but still. return $this; > final public function deregister($user) < //here's why $this->users should be an assoc array foreach ($this->users as $k => $obj) < if ($obj === $user) users[$k]); break; > > return $this; > > class OptimistTrait extends Trait < protected $name = 'Optimist';//use constants for this //same methods as above go here, except for one crucial difference: //pass user instance to this method //additional params depend on the method public function setSmile($user) < //don't use $this here, use $user >> class Creature < protected $traits = [];//default is no specific traits /** * Allow passing of traits via the constructor, if you want to. */ public function __construct(array $traits = []) < foreach ($traits as $trait) $this->addTrait($trait); > final public function addTrait(Trait $trait) < $this->traits[$trait->getName()] = $trait->registerUser($this); > /** * @return bool */ final public function hasTrait($name) < return isset($this->traits[$name]); > public function dropTrait($name) < if (isset($this->traits[$name])) < $this->traits[$name]->deregister($this); unset($this->traits[$name]); > > public function __destruct() < foreach ($this->traits as $trait) < $trait->deregister($this); > $this->traits = null;//make sure the instances are no longer referenced > > class Steve extends Human < public function __construct(array $traits = []) < //set default traits in constructor //you could declare a $requiredTraits property that prevents //the dropTrait method from removing these $traits[] = new OptimistTrait; parent::__construct($traits); >/** * Expose default/required traits directly */ public function doOptimistThings(Creature $with) < $this->tratis['Optimist']->callMethod($this, with); > /** * If you want to, though I'd not recommend this, you can expose the traits directly * Note that __call is slow, and this makes your code more error prone and harder to test * @throws BadMethodCallException */ public function __call($method, array $args) < foreach ($this->traits as $trait) < if (method_exists($trait, $method)) < array_unshift($args, $this);//prepend instance to args return call_user_func_array([$trait, $method], $args); >> throw new BadMethodCallExcpetion( sprintf( '%s::%s is not callable, trait is missing or method is not defined', __CLASS__, $method ) ); > >

    Now we can easily check whether or not a particular instance has a particular trait using a simple $instance->hasTrait(‘Optimist’); call. Furthermore: if some traits are required, we can simply declare the trait methods in the class itself. And before you go on to say that this defeats the point, and causes code duplication, let me point out that: yes, it does cause some code duplication: a method declaration with a single line: return $this->traits[$name]->method($this, $arguments); . Thats one line, not the same method that is repeated throughout. It also allows you to add something extra to the trait method: execute it and perhaps tally the number of calls on that trait (for whatever reason). Using this approach, these “traits” act more like parent methods, so it’s actually a more accurate way to mimic multiple inheritance:

    public function inheritExample() < $this->calls[__METHOD__] += 1; return parent::inheritExample(); > vs public function pseudoTraitExample() < $this->calls[__METHOD__] += 1; return $this->trait['name']->pseudoTraitExample(); >

    Another objection you might have with this approach is that it is seemingly more verbose. But is it really? remember: there’s no need for tons of checks to see whether or not an object actually implements a given trait. You’ll probably write this code once, and basically use that abstract trait-supporting class as base for all of the classes that will require traits. I really don’t think that there will be that much of a difference in terms of lines of code, or duplicate lines at all.

    Even if there were a difference, I still find this (using separate classes instead of weak abstract subsets) the better option. Calling hasTrait tells you all you need to know, you just know what methods will be available, and what they’ll do. There’s no aliases to muck things up, and no diamond problem to worry about. The traits act as a sort of namespace, so there’s no chance of method-name conflicts, whereas combining traits in classes leaves the conflict resolution up to the implementing class, which means it’s something that can change depending on who resolved the conflict, or what method was needed by the last person working on the code.

    Источник

    Читайте также:  Python test if tuple
Оцените статью