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.
Related
This morning, I've been notified that a new Twig_Extensions release is available! Yay!
Before integrating it to twigfiddle, I wanted to see changes. This is mainly adding support to namespaces using class_alias function, and then add PSR-4 correspoding classes that just include the legacy one.
But each new (namespaced) classes are implemented like this:
<?php
namespace Twig\Extensions;
require __DIR__.'/../lib/Twig/Extensions/Extension/Text.php';
if (\false) {
class TextExtension extends \Twig_Extensions_Extension_Text
{
}
}
What does this notation mean?
It means it's using the false defined in the global namespace..
After a bit of research it turns out the rest of this answer is nonesense... I could swear you were able to do this in PHP at one point in time.
I think this is get around the situation where
<?php
namespace whywouldyoudothis;
false = true;
?>
I have never ever seen anyone code for this but that's what springs to mind.
From php manual
Prefixing a name with \ will specify that the name is required from
the global space even in the context of the namespace.
if (\false) {
class TextExtension extends \Twig_Extensions_Extension_Text
{
}
}
The code is still reachable by code sniffers and IDEs. However I think it should have deprecation note there. So that developers would be notified about using deprecated classes.
Here is an example from main Twig repository.
https://github.com/twigphp/Twig/blob/v2.10.0/lib/Twig/Token.php
This is a no sense code, simply this is a Unreachable code because \false is always false!
I'm working on a library to connect to the Eventbrite API. I've made it generic enough that a lot of the second level business objects are empty classes. Having said that, when I instantiate those objects, I would still like them to register as different classes. I thought class_alias would be the way to go, but it seems that the original class is what is returned when doing a var_dump.
Current:
<?php
namespace Project;
class_alias(
'\\Project\\Classes\\Aliaser',
'\\Project\\Classes\\Attendee',
true
);
use Project\Classes\Aliaser;
use Project\Classes\Attendee;
$attendee = new Attendee();
var_dump($attendee)
// Aliaser {}
What I'm shooting for:
$attendee = new Attendee();
var_dump($attendee);
// Attendee {}
I would really like to delete the empty classes in favor of the generic one while also having the new dynamically generated class be registered.
Is that possible without a serious performance hit?
Note: Prefer PHP 5.4 or greater, but PHP 7 is also good.
You can create an instance of a class without puting the code to a file by using eval:
// define the class if it does not exists
if (!class_exists (\Eightfold\Eventbrite\Classes\ApiResource\Question::class)) {
eval ( 'class Question extends \Eightfold\Eventbrite\Classes\ApiResource {} ');
}
//create instance
$instance = new \Eightfold\Eventbrite\Classes\ApiResource\Question ();
P.S. If you don't find another solution without eval then you should consider this quote:
If eval() is the answer, you're almost certainly asking the wrong
question. -- Rasmus Lerdorf, BDFL of PHP
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 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.
Just a quick question on your preference of using PHP namespaces or class prefixing.
<?php
// ----- namespace -----
use My\Namespace;
$object = new Namespace\Object;
// ----- prefix with PR -----
$object = new PF_Object; //or
$object = new PFObject;
Which do developers prefer? I know why the use of namespaces can bring great advantage to applications, but also can quite a hindrance in PHP in my own opinion.
Thanks!
Combine use with an alias:
use My\Namespace\Foo as Foo;
$object = new Foo;
It's also useful like so:
namespace My\Debug\Stuff;
use My\Production\Stuff\Foo as BaseFoo;
class Foo extends BaseFoo {}
Why would you consider namespaces a hindrance?
class prefixing seemed to me like a sort of a hack to implement 'in code' a mecanism to implement namespaces.
Newer code now has the option to use a native built-in way of handling namespaces. This is a much cleaner approach, in my very humble opinion.
Consider this popular yet eye-opening example that allows legacy code to use namespace:
// Using native namespace features to shorten class prefixes
<?php
use Sabre_DAV_Auth_Backend_PDO as AuthBackend;
use Zend_Controller_Action_Helper_AutoComplete_Abstract as AutoComplete;
$backend = new AuthBackend();
?>
Clearly, there's no need to use the underscore character to fake namespaces any more, so I suppose the question boils down to "is it a good idea to use underscore characters in class names".
IMO, the answer is no, firstly because it looks ugly (IMO) and secondly because some older class loaders could get confused by a class name that includes an underscore.
well
if you are running PHP 5.2.X you only have the option 2
but if you are running PHP 5.3.Xyou could use both.
In my case running PHP 5.3.X I would use the feature that the new version of the language offers. To make an analogy is likely be running JAVA 1.6 and don't use generics (or sort of)