0

Many places in the core code that need to use the name of a class as a string will use it as \Magento\Module\Classname::class rather than simply '\Magento\Module\Classname'.

The benefit is clear if you've imported the class with use, in which case it is a shortcut to repeating the full namespace, but in many instances ::class is used even with the fully-qualified name. This seems to be most common in test classes, but it's not only true there.

What is the reason for this pattern?

Edit: Franck Garnier pointed out in an earlier version of answer that this is required by the coding standards, but that just pushes the question back a level. Why do the standards require this (particularly in contrast to an absolute class name string literal)?

2 Answers 2

1

I try to explain the use of ::class.

Magento 2 uses ::class because it is specified in the framework's coding standard.

The Magento 2 documentation page reference is here : https://devdocs.magento.com/guides/v2.2/coding-standards/code-standard-php.html

Class name resolution standard

For class name resolution, use the ::class keyword instead of a string literal for every class name reference outside of that class. This includes references to:

Fully qualified class name
Imported/non-imported class name
Namespace relative class name
Import relative class name

Some other useful StackOverflow answers provide justification for this: https://stackoverflow.com/questions/30770148/what-is-class-in-php

It's very useful for 2 reasons.

You don't have to store your class names in strings anymore. So, many IDEs can retrieve these class names when you refactor your code

You can use the use keyword to resolve your class and you don't need to write the full class name.

This feature is also useful for Late Static Binding.

Instead of using the __CLASS__ magic constant, you can use the static::class feature to get the name of the derived class inside the parent class.

Then the PHP RFP explain a little bit more about the why the syntax was introduced: https://wiki.php.net/rfc/class_name_scalars

The ClassName::class syntax was chosen because it can not clash with existing constants (as class is a keyword). The feature addition thus is fully backwards compatible.

And:

Class names in strings have to be fully qualified in PHP. It is not possible to utilize aliases registered through use statements:

use A\Namespaced\ClassName;

// this will try to create a mock of the global class ClassName, not
// of the aliased class A\Namespaced\ClassName
$mock = $this->getMock('ClassName');

ClassName::class allows the programmer to easily obtain the fully qualified class name from an aliased name:

use A\Namespaced\ClassName;

// ClassName::class resolves to 'A\Namespaced\ClassName'
$mock = $this->getMock(ClassName::class);
6
  • Thanks for the dev docs link. Seeing it there officially explains at a proximal level why the pattern is followed. Still not clear on why that's the standard, though. I acknowledged in my question that it makes sense for non-absolute class names, but I'm trying to understand why it's required in lieu of an absolute class name string literal. Oct 2, 2018 at 13:07
  • I agree with you. Code Convention is sometime mysterious. To my mind it is for a better maintainability if developers follow some code convention. Oct 2, 2018 at 15:03
  • Oh, absolutely. Convention is great; I just like to also know the reasons for it. Generally it's not determined out of the blue. :-) Oct 2, 2018 at 16:32
  • Yes sure. To my mind, the possibility to use namespace aliases with ::class is the main reason. You can change the base class without to change all the full class name string in your application. Oct 3, 2018 at 8:46
  • 1
    I added some source to my answer. Oct 3, 2018 at 8:52
0

Using ::class works with classes that do not exist, and classes that do exist by are not loadable for some reason.

Add this code anywhere and verify it works without problems

echo \ImaginaryNamespace\MyNonExistingClass::class;

So, in a sense, it guarantees that you will get a string no matter what, instead of having problems to compile.

1
  • I'm asking why use that instead of just a string literal? Naturally, a string literal will always be a string. :) Edit: realized I hadn't quoted my string in my question. Fixed. Oct 2, 2018 at 1:55

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.