Symfony2, EntityManager::getRepository(Namespace\To\Some\Class::class OR '**Bundle:Entity') - php

Symfony2 docs say that I should use alias shortcut 'ByBundle:myEntity' for entity path:
$em->getRepository('ByBundle:myEntity');
But this string literal is not usefull - no refactoring, no fast and auto renaming of the entity class in IDE.
I use magic method ::class
$em->getRepository(\ByBundle\Entity\myEntity::class);
The Question: am I doing this right?

In fact the Symfony2 core team is using the ::class method for example for adding form field types like so: $builder->add('name',TextType::class,array(...)) since Symfony v2.8 i guess there's nothing wrong the way you do it.
UPDATE:
This allows your IDE to throw an exception if the linked entity class namespace would change and you will be able to recognize this while the development process. That is definitely a "it's better to be safe than sorry" way of how to map the entity instead of having the full qualified namespace or even the alias as a string.

Yes. Using class reference is always better than string refence.
Using string usually means there is algorithm, that converts string to the class.
IDE friendly is also desired.

Related

Laravel - referencing the class

I've been reading a lot of documentation for Laravel during last week for the sake of learning what kind of beast it is.
I noticed one thing that whenever somebody references some class he references to it as string, e.g.:
public function user()
{
return $this->belongsTo('App\User');
}
Pay attention to 'App\User'
Taken from here https://laravel.com/docs/5.5/eloquent-relationships#polymorphic-relations
I wonder why don't they reference it as App\User::class ?
In this case it's easier to type and support the code, because it's easier later to follow the class pressing Ctrl+B. Also refactoring is easier and it's harder to make a mistake because IDE will warn you that class doesn't exist if you make a typo.
I see no reasons to reference class User as 'App\User' instead of App\User::class.
Do you see any?
Taking from PHP doc Class Constants:
The special ::class constant are available as of PHP 5.5.0, and allows for fully qualified class name resolution at compile, this is useful for namespaced classes:
This means that using User::class will at runtime resolve to 'App\User' according to the example you gave. So the choice is yours.
On a personal note, In order to avoid typographical mistakes with strings I prefer to use the class constant resolution, and also I can easily check the usage from my IDE.
Also I do not have to memorise the namespace of the class I am using.
Apart from these benefit, I do not see any difference unless there is performance difference which obviously does not seem so.
The actual string is used to illustrate that it is the full class name of the related model. You can very easily use Model::class. The example in the docs is explicit and removes any potential guess work from someone reading that argument.

Symfony2 classess and repository name

That is simple for you, but I can't understand the difference (if it exist) between two "name" of this same class:
First if I use php function (get_class()) for some entity I get something like structure to directory to class of this object (App\Module\Class).
Second: If i want to get some data form db I have to use a repository name as AppModule:Class
So is there any method to transform first naming to second?
I don't know how you naming this two methods, I am sorry for my mistakes.
If you use ClassName::class where ClassName is whatever a class is, you'll obtain the class FQCN (Fully Qualified Class Name; in your example, for instance, App\Module\Class)
I suggest to use ClassName::class every time you can instead of VendoBundle:Class convention
This will work only if you use PHP >= 5.5 btw, but I hope you do!

PHPUnit using annotations to assert exception vs method call

There are two ways to assert the exception in Phpunit:
using annotation #expectedException
using method call $this->expectException()
I've tried both of them, they work fine and exactly the same.
Which is the correct way?
Are there any guidelines on which one should be used?
PS: When the exception is based on some condition and does not always happen then obviously the method should be used.
Using expectException() is considered best practice, see this article.
There's a few clear advantages for me on why I'd choose to use the method rather than the annotation.
In the annotation form, you have to use the full namespace to the class name for it to work:
#expectedException MyException // Not found unless it is within the current namespace
#expectedException \Some\Deep\Namespace\MyException // works
The alternative:
$this->expectException(MyException::class); // works, with a 'use' statement
This is more readable, more explicit, flexible (automated refactoring/renaming would be a doddle in most editors like PHPStorm), is less code to write, and is in line with the standard test method setup of the 3 phases in correct order, Arrange, Assert, Act. Lastly, the annotation internally would need to be parsed, and would only call the expectException method anyway. So it's going to be more efficient as well.

Can I use a namespaced class with stream_wrapper_register?

I have a class VarStream that I would like to register like
stream_wrapper_register('var', 'VarStream');
Our classes are always namespaced, so I've tried
stream_wrapper_register('var', '\OurSpace\VarStream');
with no luck.
Can I use namespacing when registering a stream wrapper?
Yes you can. You need to provide the FQCN (Fully-Qualified-Class-Name) of the stream wrapper class.
You might think that in the code you provided you have it already:
stream_wrapper_register('var', '\OurSpace\VarStream');
But that is not the case as the FQCN never starts with the back-slash "\".
Instead use (just) the class-name of that class:
stream_wrapper_register('var', 'OurSpace\VarStream');
Normally the leading backslash is not necessary. In this case even, it prevents proper use. It is not part of the (fully-qualified) class-name. This is normally always the case when you pass class-names as string parameters.
I've solved such problem with usage of ::class, which
allows for fully qualified class name resolution at compile
For example,
stream_wrapper_register("stream", self::class)
So you don't have to think about (back)slashes by yourself ;]

Load a class with a different name than the one passed to the autoloader as argument

basically, I have the following problem: I want to make use of PHP's new namespace features. Unfortunately, I'm running a PHP version (5.3.2) in which namespace-autoload-support for linux still seems buggy and does not work (PHP should be able to load the class file automatically by its namespace without having to use a custom autoloader, but that doesn't work).
What I want to achieve is to write an autoloader that I can simply remove as soon as the php's namespace features work correctly (there seems to be a speed advantage when not using a custom autoloader) with having to change as less code as possible afterwards.
So I have a call like this:
$filereader = new system\libraries\file\XML();
which gets passed correctly as the string "system\libraries\file\XML" to my autoload-function. I can load the corresponding file "system/libraries/file/XML.class.php". However, the class in there will be named
class XML { ... }
(or something different than "system\libraries\file\XML") and so have a different name than the one by which PHP will try to load it. So is there an easy way to load that class ("XML") which has a different name than the name which I pass to the autoloader function? Can I perhaps do something in the autoloader to achieve that behaviour? (I'm using spl_autoload_register).
I know that even if it worked out I would still not be able to use all features of namespacing, since a (simple) autoloader would not respect the "use namespace" directive and I would still have to use rather long names for loading a class. However, if I understood PHP's namespace-features correctly, I could leave the code as it is when I later switch to using native namespace support instead of my autoloader.
If what I try to do does not make sense at all in your opinion or if I misunderstood namespaces, please tell me (- I have not used PHP's namespace features yet).
I would load the file (which creates the XML class) and then alias the XML class to the properly namespaced system\libraries\file\XML class:
class_alias('XML', 'system\libraries\file\XML');
More generally:
class_alias(basename($class), $class));
Though I'm not quite sure whether class_alias can alias to namespaced classes...

Categories