I have studied the use of Namespaces in PHP a while back but recently looking at a project that used the use keyword and then accessed the namespaced object as if they were normal without namespace.
My question is, is the code below correct, it hs a file index.php and uses the namespace MyLibrary\Base it then uses use to bring in \MyLibrary\Registry \MyLibrary\User and \MyLibrary\Request
It then can access any of these object without putting there namespace in front of them, so the actual code below the use section looks like a normal pre-namespace php file.
I am asking if this is how you use namespaces? Or am I missing something?
File: index.php
<?php
namespace MyLibrary\Base;
use \MyLibrary\Registry;
use \MyLibrary\User;
use \MyLibrary\Request;
class Base
{
public $registry;
function __construct($registry)
{
$this->registry = $registry;
$this->user = New User;
$this->request = new Request;
# code...
}
}
?>
File: registry.class.php
<?php
namespace MyLibrary\Registry;
class Registry
{
public $user;
function __construct($user)
{
$this->user = $user;
# code...
}
}
?>
Yes. The use-statement imports the class- or namespace-name into the current scope. To write everything that short is the reason, why the PHP-devs implemented namespaces ;)
namespace MyFirstNamespace {
class Foo {}
}
namespace MySecondNamespace {
use \MyFirstNamespace\Foo as Bar;
$foo = new Bar;
}
a) it make everything more readable, because its much shorter, than Vendor_Package_Foo_Bar_XyzClass and b) you can exchange the classes to use very fast.
# use \MyFirstNamespace\Foo as Bar; // I don't like Foo anymore
use \MyFirstNamespace\SimilarToFoo as Bar;
Namespacing has a lot of advantages to it.
The first on is you can reuse method names and even class names if it makes sense provided they exist within a different namespace. Example:
namespace \myNamespace\data\postgres;
class DataBase extends \PDO
{
}
namespace \myNamespace\data\mysql;
class DataBase extends \PDO
{
}
You could even reuse names that are normally reserved for PHP functions
namespace \myNamespace\dir;
function makedir ()
{
if (// some condition is true)
{
\makedir ();
}
}
All of this is intended to make it easier to use code from different sources together without having to worry about naming conflicts. Provided programmers are courteous enough to observe a few simple rules then the chances of name conflicts are hugely reduced. Actually, pretty much the only rule you need to concern yourself with to avoid naming conflicts is to make the first level of your namespace your own. For example, use your company name, or some other way of identifying you as a unique vendor as the first level of your namespace and everything should be good.
For example I use \gordian as the root namespace in all the code I write, as I can then call my classes under that namespace anything I like without worrying about them colliding with someone who chose a different root namespace.
So what's wrong with PEAR conventions, you might ask? A lot of projects follow them, including the popular Zend framework.
The answer is names become very unwieldy very quickly. For instance, Zend, as it follows the PEAR convention, uses a sort of pseudo-namespacing. All the classes in the collection start with Zend_ and with each level of class hierachy add a further part to the name.
Ze
As a result, you end up with class names like Zend_Db_Adaptor_Abstract and Zend_Dojo_Form_Decorator_TabContainer.
Should Zend update their framework to use namespaces (which I'm told is happening with Zend Framework 2.0) then they'd be replaced with \Zend\Db\Adaptor\Abstract and \Zend\Dojo\Form\Decorator\TabContainer instead. So what, you might ask? The answer is that you can alias them to much shorter names with the Use keyword, as you've already seen. This means you don't have to keep writing the full class name out, but only as far as to what you've aliased.
use \Zend\Dojo\Forn\Decorator as Dec;
$a = new Dec\TabContainer; // Not easy to do without namespaces!
Further more, if you're already in a given namespace, then you don't even have to use the use keyword to access other items within the same namespace by a short name, as it happens automatically for you in that case. For framework writers this is a huge timesaver.
For example, you might see something like the followign in Zend Framework 2 (as I'm not working on it in any way, this is purely an example and not from the actual ZF2 source).
namespace \Zend\Db\Adaptor;
class Postgres extends Abstract // We don't need to use \Zend\Db\Adaptor\Abstract here because it's in the same namespace already anyway
{
}
There are other benefits too, such as it makes autoloaders ridiculously simple to make (provided your namespace structure maps exactly onto your filesystem directory structure).
Namespaces can seem like one of those features that aren't really very important, or don't even seem to make any sense, but after using them for a little while their usefulness will suddenly become very obvious.
Related
I include myfile.php file 2 times.. I want to know if there is way to put in the start of myfile.php something like this:
if($authorized){
Namespace MyProject;
}
function ABC(){}
function EFG(){}
(I do this to avoid function-redefine errors. Please dont ask me why I do such thing.. I know there are if function_exists and etc.. but I need answers to what I ask).
update:
I do this, because I need to define function XYZ() and using that before other framework is loaded (which newly defines globally function XYZ()). So I want to use that function (with different functionality) before framework loads, and after framework loads, it should behave as framework decides.
Is there a way to make namespace's conditional?
Although this is impossible directly, I could suggest using the define() method to create this yourself. Where the file requiring the class needs to have a allowed definition to access the file.
define('IN_NAMESPACE', 0);
if(defined('IN_NAMESPACE')) {
// authorized
}
But if you're worrying about a class name being repeated, namespaces are for the declaration of environments so you do not get duplicates, for example:
namespace Environments\One;
class Example { }
namespace Environments\Two;
Class Example { }
use Environments\One\Example as ExampleOne;
use Environments\Two\Example as ExampleTwo;
$e_o = new ExampleOne();
$e_t = new ExampleTwo();
Or simply, directly say you will use this environment like so:
$e_o = new Environments\One\Example();
$e_t = new Environments\Two\Example();
But again, this issue is not canonical to PHP. Use MVC methodologies to over-come these issues and Singleton/Dependency Injection design patterns.
Why would we use the class_alias function? For example:
Class Test {
public function __construct(){
echo "Class initialized";
}
}
class_alias("Test", "AnotherName");
$instance = new AnotherName(); # equivalent to $instance = new Test();
According to the manual, "The aliased class is exactly the same as the original class."
What is this useful for?
Surprisingly, nobody has mentioned the obvious reason why one would do this: the use keyword can only be used in the outmost scope, and is processed at compile-time, so you can't use Some\Class based on some condition, nor can it be block-scoped:
namespace Foo;
if (!extension_loaded('gd'))
{
use Images\MagicImage as Image;
}
else
{
use Images\GdImage as Image;
}
class ImageRenderer
{
public function __construct(Image $img)
{}
}
This won't work: though the use statements are in the outmost scope, these imports are, as I said before, performed at compile-time, not run-time. As an upshot, this code behaves as though it was written like so:
namespace Foo;
use Images\GdImage as Image;
use Images\MagicImage as Image;
Which will produce an error (2 class with the same alias...)
class_alias however, being a function that is called at run-time, so it can be block scoped, and can be used for conditional imports:
namespace Foo;
if (!extension_loaded('gd'))
{
class_alias('Images\\MagicImage', 'Image');
}
else
{
class_alias('Images\\GdImage','Image');
}
class ImageRenderer
{
public function __construct(Image $img)
{}
}
Other than that, I suspect the main benefit of class_alias is that all code written, prior to PHP 5.3 (which introduced namespaces) allowed you to avoid having to write things like:
$foo = new My_Lib_With_Pseudo_Name_Spaces_Class();
Instead of having to refactor that entire code-base and create namespaces, It's just a lot easier to add a couple of:
class_alias('My_Lib_With_Pseudo_Name_Spaces_Class', 'MyClass');
To the top of the script, along with some //TODO: switch to Namespaces comments.
Another use case might be while actually transferring these classes to their namespaced counterparts: just change the class_alias calls once a class has been refactored, the other classes can remain intact.
When refactoring your code, chances are you're going to want to rethink a couple of things, so a use-case like aichingm suggested might not be too far fetched.
Last thing I can think of, but I haven't seen this yet, is when you want to test some code with a mock object, you might use class_alias to make everything run smoothly. However, if you have to do this, you might aswell consider the test a failure, because this is indicative of badly written code, IMO.
Incidently, just today I came across another use-case for class_alias. I was working on a way to implement a lib, distilled from a CLI tool for use in a MVC based web-app. Some of the classes depended on an instance of the invoked command to be passed, from which they got some other bits and bolts.
Instead of going through the trouble of refactoring, I decided to replace the:
use Application\Commands\SomeCommand as Invoker;
Statements with:
if (\PHP_SAPI === 'cli')
{
class_alias('\\Application\\Commands\\SomeCommand', 'Invoker');
}
else
{
class_alias('\\Web\\Models\\Services\\SomeService', 'Invoker');
}
and, after a quick :%s/SomeCommand/Invoker/g in vim, I was good to go (more or less)
Think of this the other way. There is a library and it contains a class called MySq, as the library moves on in development they think 'oh maybe we should just make one database class' so the rewrite the class and call it 'DatabaseConnection' it has the same functions as the MySql class but it can also handle Sql and MsSql. As time goes on and they release the new version 'PHPLib2'. The developer has now two options: 1, tell the users to change from MySql to DatabaseConnection or 2, the developer uses
class_alias("DatabaseConnection","MySql");
and just mark the class MySql as deprecated.
tltr;
To keep version compatibility!
It can be used for:
Changing strange class names of ext. scripts/sources (without the need to rewrite the code)
Making class names shorter (the class alias can be used application wide)
Moving classes to another namespace (#tlenss)
I want to do something like class categories in Objective-C, to define a class in one file, implement some core methods there, then implement some helper methods in another without subclassing or interfaces, just "continue" the class.
Possible in PHP?
As of PHP 5.4, you can accomplish this with Traits. To quote the official documentation:
Traits [enable] a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. [...] A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own. It is an addition to traditional inheritance and enables horizontal composition of behavior; that is, the application of class members without requiring inheritance.
Using a trait allows you to store helper methods that address cross-cutting concerns in a central place and use these methods in whatever classes you need.
// File "HelperMethodTrait.php"
trait HelperMethodTrait
{
public function myIncredibleUsefulHelperFunction()
{
return 42;
}
}
// File "MyClass.php"
class MyClass
{
use HelperMethodTrait;
public function myDomainSpecificFunction()
{
return "foobar";
}
}
$instance = new MyClass();
$instance->myIncredibleUsefulHelperFunction(); // 42
a-priori PHP doest not give you this feature by language construction, the whole class must be in a single file.
Now there are tricks that could do the stuff, but they are quite heavy CPU demanding:
You can for example dissociate your classes between different files, then load the files and build a single string with the whole code, then do an eval(string) to interprete the classes and build them into the runnable code area.
not really a good idea btw for many reasons
If your only goal is to make the class definition file smaller, you can include files within a function definition
class MyClass {
public function doStuff($foo,$bar) {
global $quz;
include('MyClass.doStuff.php');
}
}
Within the include, your local scope applies ($foo,$bar and $quz will be defined)
I'm not sure what the overhead is - the include seems to happen at run-time, not compile time (since an include can actually return a value ..)
I think you better split your class in n parts along functional criteria, and then use the dependency injection pattern to "inject" class A into class B in the constructor for B, without a need for subclassing/interfaces.
You could use this method to add functions to some objects externally, which is different from adding methods to the class itself.
https://stackoverflow.com/a/2938020/2277620
Another not-so-good-way is it create a multiple subclasses so every level of subclasses add only a 'group' of functions.
I used this trick in a single case where a class was more than 10k rows.
Now I've 6 levels of inheritance where every level add a single 'category' of functions the the "previous level" class.
Not so cpu-consuming, ugly to see, not so difficult to maintain
It is highly dependant on what you wish to achieve. I had this bright idea doing what you wish to do. I likes the key words set, get run delete etc. Suppose there was a class and I wanted set of delete. As Ph.T pointed out class needs to be in single file
So make abc->set in one file and abc->get in another file made no use and sense.
So had to lot of rethinking and think of classes as micro services doing specific tasks broken down in functionality.
Solution went with name spacing.
namespace A;
class Get{public static function myCode(){}
public static function myAnotherCode(){}}
this would then be called A\Get::myCode(); or A\Get::myAnotherCode();
Similarly set would be
namespace A;
class Set{public static function myCode(){}
public static function myAnotherCode(){}}
This would then be called A\Set::myCode(); or A\Set::myAnotherCode();
Then user spl_autoload_register to load classes remember to replace \ with /
spl_autoload_register(function ($class) {
require_once __DIR__ . '/' . strtolower(str_replace('\\', '/', $class) . '.php')
});
and directory structure is as following
main (folder)
-- A (folder)
-- set.php (file)
-- get.php (file)
we asked for A\Get::myCode()
require would see it as A/Get.php then run its logic whether it is right name space or class etc.
good side of it if planned out right is it would force you to run things run in logical not just wishy washy there and there. Second you would only load functionality what you need not just whole bunch of this and that.
down side two parts of classes wont share between them unless one extends one from another which would defy the whole logic because other one would be loaded as a consequence any ways.
Careful negation has to be made as in what logic and planning data will be shared and has to be worked out before hand.
namespace A;
class Universal {
protected static $share_one;
protected static $share_two;
}
namespace A;
class Set extends Universal {
public static function myCode(){ parent::$share_one ='wow';}
}
namespace A;
class Get extends Universal {
public static function myCode(){ return parent::$share_one;}
}
main (folder)
-- A (folder)
-- universal.php (file)
-- set.php (file)
-- get.php (file)
run the code and see the magic
A\Set::myCode();
echo A\Get::myCode();
if you only need one set of functionality e.g. get then just use get echo A\Get::myCode(); would work without errors.
To be honest without playing around with name spaces its just expenditure of time earning headaches.
Side note: if done right it can speed up things as class universal wont load twice. even if called gazillion times whats what we want load defaults and then populate them where ever we need them. I have made huge classes where besides defaults only needed few functions rest was just memory load. breaking down just spead up things.
Recently I have started to play around with Namespaces in PHP, I am not a fan of the chosen Namespace separator / (as most others have a mutual feeling) /
Below I have a very basic/simple example of using Namespace in PHP.
I have a Registry.class.php file that has a Registry class that is in the Namespace Library
I also have the file Controller.class.php below that has a Controller class that is in the Namespace called Project
Now in this Project Namespace I need access to the Registry object that is in a different Namespace, Library So I use use Library\Registry to Import that Namespace
With that done, I am able to simply access my Registry class like this...
$this->registry = new Registry;
Now if I had not used use Library\Registry then I would have to access it like this
$this->registry = new /Library/Registry;
So this is where my question begins.
For this simple example I am just bringing in the Registry class, in a real project, imagine several other classes and namespaces being brought in, So I would be using
use Library\Registry and use Library\SOME OTHER CLASS and use Library\YET ANOTHER CLASS etc...
I can then operate on the Objects/classes as if they were in this namespace to begin with so instead of pre-fixing the class name with its appropriate Namespace name, I simply just instantiate the class by its name ( new Registry;) instead of new /Library/Registry;
I would like to know if this is considered bad practice or not? It greatly simplify's things and makes the code look cleaner IMO, but if there is anything bad about this method I would like to know before I write a lot of code using this method. Should I be pre-fixing my classes when I instantiate them with their namespace INSTEAD of importing them with the use /Path/to/Namespace/Classname ?
Please share your knowledge with me, I realize it will work either way but I want to make sure. Example classes and namespaces are added below:
Controller.class.php
<?php
namespace Project
{
use Library\Registry;
class Controller
{
public $registry;
function __construct()
{
include('E:\Library\Registry.class.php');
$this->registry = new Registry;
}
function show()
{
$this->registry;
echo '<br>Registry was ran inside testcontroller.php<br>';
}
}
}
?>
Registry.class.php
<?php
// Registry.class.php
namespace Library
{
class Registry
{
function __construct()
{
echo 'Registry.class.php Constructor was ran';
}
}
}
?>
One of the primary purposes of namespaces is to prevent name conflicts in large code bases and across shared code and imported libraries. If you're not having name conflict issues, then I don't necessarily see anything wrong with using each class. If you find yourself doing this for all your classes, however, then I would question why you're using namespaces in the first place. This would only seem to make sense to me if your code was going to be used as an API or library by someone else.
I've just begun learning Symfony2 (after using 1.x for the past 2 years) and am kind of put off by how much more typing is required. I know that sounds lazy, but I love the fact that I can quickly get something up and running in 1.x with much less typing. I'm wondering if it's possible to autoload classes without needing to use namespaces. All my attempts to do so (using the PEAR naming scheme) have failed.
If I'm missing something obvious and would be shooting myself in the foot by avoiding using namespaces, I'd appreciate any advice :)
In response to #KingCrunch:
I'd like to avoid the namespace and use declarations that seem to be used very frequently in Symfony2 simply to speed up my coding. To be honest, I haven't used namespaces in PHP before. I understand their benefit on paper (and I'm used to using packages in other languages) but I've never run into an issue by not using them in Symfony 1.x projects. This is why I made the "If I'm missing something..." statement above.
You have to realize that namespaces are not requiring you any more typing than PEAR-style names. Actually they can save up some characters.
See those two examples:
With PEAR-style:
class Foo_Bar_Baz extends Foo_Bar_Parent
{
public function __construct()
{
$obj = new Some_Long_Class_Name;
$obj2 = new Some_Long_Class_Name;
}
}
With namespaces/use:
namespace Foo\Bar;
use Some\Long\Class\Name;
class Baz extends Class
{
public function __construct()
{
$obj = new Name;
$obj2 = new Name;
}
}
With namespaces, but no use:
namespace Foo\Bar;
class Baz extends \Foo\Bar\Class
{
public function __construct()
{
$obj = new \Some\Long\Class\Name;
$obj2 = new \Some\Long\Class\Name;
}
}
As you see, if you use fully qualified class names every time (last example), you just have one more char per class name, the leading \. If you use the use statements and all, then it gets shorter the more you re-use the same class names in one file, or the more classes you use that are in the same namespace.
TL;DR: Anyway, if you're lazy, get an IDE like PhpStorm that will autocomplete all those and add the use statements for you.
Short answer: yes, namespaces are a must if you want to use Symfony2.
The reason behind this is that sf2 class autoloader is built on the namespace usage. In theory, you could write your own autoloader and wrap it around sf2, but I think this would be more hassle than using namespace and use ;)
At first I was also bummed by it and didn't really like the way it's used. But once I got used to it and started to see the benefits, it's the other way around. I use sf2 for my own projects and must use sf1.4 at work (not for long, hopefully) and every time I switch from sf2 to sf1.4 I get the "oh, not this again" feeling.
NS is so complex that you can even make a mistake when trying to explain the benefits to someone:
I know the point of the answer wasn't to get the code "perfect", but still...You forgot to include the use statement for the "Class" class:
namespace Foo\Bar;
use Some\Long\Class\Name;
use The\Extended\Class;
...
This is why namespaces are horrid - only takes forgetting 1 to throw an error; and, even if there is only 1 class named 'Class' in the entire project, PHP has no idea it's there.