BackSlash(\), Namespace Separator in namespaces aliasing in PHP - php

I have been reading about Using namespaces: Aliasing/Importing in PHP. There are two things I don't understand.
It says,
Note that for namespaced names (fully qualified namespace names
containing namespace separator, such as Foo\Bar as opposed to global
names that do not, such as FooBar), the leading backslash is
unnecessary and not recommended, as import names must be fully
qualified, and are not processed relative to the current namespace.
Can someone please explain
What does it mean?
What's the purpose of using namespaces aliasing ? Given that I know the purpose of using namespaces.

What does it mean?
It really means what it says and shows in the example. When importing a namespaced class, you should omit the first backslash:
use My\Full\Classname as Another; // recommended
use \My\Full\Classname as Another; // not recommended
The reason being that use expects a fully qualified namespace. You cannot use a relative path. In other words if you are in the My\ namespace already, you cannot use Full\Classname.
What's the purpose?
It's explained in the first chapter actually:
In the PHP world, namespaces are designed to solve two problems that authors of libraries and applications encounter when creating re-usable code elements such as classes or functions:
Name collisions between code you create, and internal PHP classes/functions/constants or third-party classes/functions/constants.
Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving readability of source code.
So, the purpose is to shorten and/or to avoid clashes, e.g. when you have two classes called Foo and need to use both, you have to have a way to resolve that conflict (at least if you don't want to use the fully qualified name each time):
use My\Very\Long\Namespaced\Class\Named\Foo as Foo;
use My\Other\Foo as OtherFoo;
And then you can use
$foo = new Foo;
$otherFoo = new OtherFoo;
So that's short and simple and doesn't clash. There really isn't much more to it.

You might need to import two totally separate name spaces, that happen to have the same name. Like, maybe you need to select data from mysql and then insert into oracle, and you're using some database library which uses namespacing.
use Database\Mysql\Connection;
use Database\Oracle\Connection;
$conn = new Connection(); //which one is it??
You could either skip importing a namespace
use Database\Mysql\Connection;
use Database\Oracle\Connection;
$conn = new Database\Mysql\Connection();
or alias at least one of them
use Database\Mysql\Connection as MysqlConnection;
use Database\Oracle\Connection as OracleConnection;
$conn = new MysqlConnection();

Related

ClassName::class vs 'ClassName' in PHP

In one of my projects we are having a function which validates objects like:
if( true == valObj( $someObj, 'SomeClass' ) ) {
//Do some work;
}
While using this I thought this can be written like:
if( true == valObj( $someObj, SomeClass::class ) ) {
//Do some work;
}
Now I just want to know which approach is better and why?
Or are they same?
The ::class notation is generally better as it allows for easier usage finding and thereby refactoring: If you use an IDE like PHPStorm you can easily rename a class, and it will find and update all usages of OldClassName::class to NewClassname::class. This is not the case for the hardcoded string variant.
If you use namespaces using this notation can also result in less inline characters.
If you are running a PHP version that supports this notation, use it :)
SomeClass::class returns the full namespace including the class name.
Whilst if you use the string notation you have to add the namepace (if any) yourself.
Edit:
It doesn't matter which notation you choose, although I personally prefer the string notation as it shows you directly what namespace the class is in while scrolling through code.
from php.net
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.
<?php
namespace foo {
class bar {
}
echo bar::class; // foo\bar
}
?>
This is also a magic constant. have a look at http://php.net/manual/en/language.constants.predefined.php

What does <namespace>::class mean?

In a CakePHP Plugin documentation there is the following code line: $validator->provider('upload', \Josegonzalez\Upload\Validation\DefaultValidation::class);
\Josegonzalez\Upload\Validation\DefaultValidation is the namespace, but I didn't understand the ::class. Could someone explain it? I didn't find anything in PHP documentation.
the class constant simply returns the full name of the class (with namespace) as a string. So instead of passing as string to some method that requires it, you pass it the PHP way. It just looks nice, for example:
$validator->provider('upload',\Josegonzalez\Upload\Validation\DefaultValidation::class);
AND
$validator->provider('upload', '\Josegonzalez\Upload\Validation\DefaultValidation');
Both Are Same
And another advantage of this is that, if you need full class name several times in a single file.. say onto multiple method calls as a parameter. You can simply use it on the top & then only the classname will return the full name with namespace. like this:
use \Josegonzalez\Upload\Validation\DefaultValidation;
$validator->provider('upload', DefaultValidation::class);
//you can use it on other places as well, if required.
$someOtherClass->someOtherMethod(DefaultValidation::class);
So, in short, it reduces the number of characters you need to type, and makes your code look cleaner.

PHP new keyword with directory?

I am looking at this tutorial:
http://www.joelverhagen.com/blog/2011/05/setting-up-codeigniter-2-with-doctrine-2-the-right-way/
and I see the new keyword used like so:
$doctrineClassLoader = new \Doctrine\Common\ClassLoader('Doctrine', APPPATH.'libraries');
I am not used to seeing the new keyword used with what appears to be a directory or something? I was looking through the PHP manual to find similar usage and what this means (and how it works) but didn't see what I was looking for.
Can someone explain this usage to me or point me to example code in the PHP manual.
PHP 5.3 introduced namespaces. Namespace are another way of structuring your program and the library you are working with is using them extensively. You can basically put classes and functions inside a namespace. Namespaces can be nested. In order to use them you prefix every namespace by a backslash.
You can read more about namespaces in the PHP manual.

PHP namespace removal / mapping and rewriting identifiers

I'm attempting to automate the removal of namespaces from a PHP class collection to make them PHP 5.2 compatible. (Shared hosting providers do not fancy rogue PHP 5.3 installations. No idea why. Also the code in question doesn't use any 5.3 feature additions, just that syntax. Autoconversion seems easier than doing it by hand or reimplementing the codebase.)
For rewriting the *.php scripts I'm basically running over a tokenizer list. The identifier searching+merging is already complete. But I'm a bit confused now how to accomplish the actual rewriting.
function rewrite($name, $namespace, $use) {
global $identifiers2; // list of known/existing classes
/*
bounty on missing code here
*/
return strtr($name, "\\", "_"); // goal: backslash to underscore
}
That function is going to be invoked on each found identifier (whether class, function or const). It will receive some context information to transform a local identifier into an absolute/global $name:
$name =
rewrite(
"classfuncconst", # <-- foreach ($names as $name)
"current\name\space",
array(
'namespc' => 'use\this\namespc',
'alias' => 'from\name\too',
...
)
);
At this stage I've already prepared an $identifiers2 list. It contains a list of all known classes, functions and constant names (merged for simplicity here).
$identifiers2 = array( // Alternative suggestions welcome.
"name\space\Class" => "Class", // - list structure usable for task?
"other\ns\func1" => "func1", // - local name aliases helpful?
"blip\CONST" => "CONST", // - (ignore case-insensitivity)
The $name parameter as received by the rewrite() function can be a local, unqualified, \absolute or name\spaced identifier (but just identifers, no expressions). The $identifiers2 list is crucial to resolve unqualified identifiers, which can refer to things in the current namespace, or if not found there, global stuff.
And the various use namespace aliases have to be taken into account and add some complication besides the namespace resolving and precedence rules.
So, how / in which order would you attempt to convert the variations of class/function names here?
Mental Laziness Bounty.
To make this a less blatant plzsendtehcodez question: an explainative instruction list or pseudo-code answer would be eligible too. And if another approach would be more suitable for the task, please elaborate on that rather. (But no, upgrading PHP or changing the hoster is not an option.)
I think I've figured it out meanwhile, but the question is still open for answers / implementation proposals. (Otherwise the bounty will obviously go to nikic.)
In an existing question on migration of namespaces to pseudo namespaced code I already introduced a conversion tool I have written as part of a larger project. I haven't maintained this project anymore since that point, but as far as I remember the namespace replacements did work. (I may reimplement this project using a proper parser at some point. Working with plain tokens has proven to be quite a tedious task.)
You will find my implementation of namespace -> pseudo-namespace resolution in the namespace.php. I based the implementation on the namespace resolution rules, which will probably be of help for you, too.
To make this a less blatant readmycodez answer, here the basic steps the code does:
Get the identifier to be resolved and ensure that it is not a class, interface, function or constant declaration (these are resolved in registerClass and registerOther by simply prepending the current namespace with ns separators replaced by underscores).
Determine what type of identifier it is: A class, a function or a constant. (As these need different resolution.)
Make sure we do not resolve the self and parent classes, nor the true, false and null constants.
Resolve aliases (use list):
If the identifier is qualified get the part before the first namespace separator and check whether there exists an alias with that name. If it does, replace the first part with the aliased namespace (now the identifier will be fully qualified). Otherwise prepend the current namespace.
If identifier is unqualified and the identifier type is class, check whether the identifier is an alias and if it is, replace it with the aliased class.
If the identifier is fully qualified now drop the leading namespace separator and replace all other namespace separators with underscores and end this algorithm.
Otherwise:
If we are in the global namespace no further resolution required, thus end this algorithm.
If the identifier type is class prepend the current namespace, replace all NS separators with underscores and end this algorithm.
Otherwise:
If the function / constant is defined globally leave the identifier as is and end this algorithm. (This assumes that no global functions are redefined in a namespace! In my code I don't make this assumption, thus I insert dynamic resolution code.)
Otherwise prepend the current namespace and replace all namespace separators with underscores. (Seems like I got a fault in my code here: I don't do this even if the assumeGlobal flag is set. Instead I always insert the dynamic dispatch code.)
Additional note: Don't forget that one can also write namespace\some\ns. I resolve these constructs in the NS function (which is also responsible for finding namespace declarations).

php static magic variable set function

I have some code I'm working with that was written by the guy before me and I'm trying to look it over and get a feel for the system and how it all works. I am also fairly new to PHP, so I have a few questions for those willing and able to provide.
The basic breakdown of the code in question is this:
$__CMS_CONN__ = new PDO(DB_DSN, DB_USER, DB_PASS);
Record::connection($__CMS_CONN__);
First question, I know the double underscore makes it magic, but I haven't been able to find anywhere exactly what properties that extends to it, beyond that it behaves like a constant, kind of. So what does that mean?
class Record
{
public static $__CONN__ = false;
final public static function connection($connection)
{
self::$__CONN__ = $connection;
}
}
Second, these two pieces go together. They are each in separate files. From what I've read, static variables can be referenced in the same way as static functions, so couldn't you just call the variable and set it directly instead of using the function?
I get the feeling it's more involved than I am aware, but I need to start somewhere.
This isn't a magic variable. The person who wrote that shouldn't really use double underscores for variable names like that because it can cause confusion.
This is just a static property on a class. Which means it is shared between instances of that class (in the same php request).
Have a look at the docs for static properties if you're unsure on how these work.
There are several predefined "magic constants" that use this naming style. However, I don't think the underscores mean anything special (as far as the language is concerned); i.e. defining your own variable like this won't bestow it any magical properties. It may be part of the previous programmer's naming convention, and if so, it's probably ill-advised.
Setting a property via a function can, in many circumstances, make the "client" code more resilient to changes in the implementation of the class. All implementation details can be hidden inside the method (known as a "setter"). However, there are strong feelings about whether this is a good idea or not (I, for one, am not a big fan).
Two underscores do not make a variable magic.
It's better to use getters/setters than to access class properties directly.
The PHP manual has this to say on naming variables (and other symbols) with underscores:
PHP reserves all symbols starting with __ as magical. It is recommended that you do not create symbols starting with __ in PHP unless you want to use documented magical functionality.
Pay particular attention to the use of the words "reserves" and "documented". They mean double underscores shouldn't be used for user-defined symbols as it may lead to future conflicts, and that unless the symbol is explicitly mentioned in the manual as being magic, it's mundane.

Categories