PHP Namespaces & Referencing Classes not contained within Namespaces - php

I have a simple question, which should hopefully have a quick answer. The code I have written makes heavy use of namespaces (I use fully qualified names everywhere); however, a piece of code (a calendar / date picker control, not written by myself) needs to be included. When I attempt to create the control, it assumes the current namespace (GUI), resulting in this error: "PHP Fatal error: Class 'GUI\tc_calendar' not found in C:\inetpub\wwwroot\Calico\calico_classes_v2.php on line 1852". Now, the calendar control itself (and it's underlying class file) does not make use of namespaces, and I am a little worried about attempting to modify it (an earlier attempt did not go well).
How can I import / include a control, that is not contained within a namespace, into the rest of my code, that does? Does PHP have something like "Import class calendar from file AS \Calendar\Calendar"?
Edit:
For additional information: I have a class, called "tc_calendar", contained in a file called "tc_calendar.php". It is not part of any namespace.
In a separate file, I have several classes (Bitmap, CompositeCalendar, EventEditor, TimeExtractor), all contained within their appropriate namespaces (GUI, Data, Extract, etc.).
In one of those classes, CompositeCalendar, contained within the GUI namespace, I am trying to create an instance of a tc_calendar. However, PHP is throwing an error (above). tc_calendar is not a part of any namspace (and definitely not a part of the GUI namespace, which PHP is just assuming, because it can't seem to find it), and I need help creating an instance of it.
tldr; $newcontrol = new tc_calendar() doesn't work; PHP tries to guess the namespace for it (because one isn't specified, because tc_calendar isn't a part of any namespace), comes up with \GUI\tc_calendar (obviously wrong). How do I access a class, not contained within a namespace, from inside a namespace?

Do you mean something like this:
namespace GUI;
use \tc_calendar as Calendar;
$myCalendar = new Calendar();
The as Calendar is optional. You could aswell keep it with the original name tc_calendar if you ommit the as Calendar.
Update
To put it in shape of the comment:
namespace {
class tc_calendar {}
}
namespace GUI {
use \tc_calendar;
class CompositeCalendar {
private function blah() {
$control = new tc_calendar();
$control->stuff();
}
}
}
I wouldn't copy paste external libraries into he same file though. It bad practise. It is better to keep them in another file and then include them and have the following:
namespace GUI;
use \tc_calendar;
require_once 'tc_calendar.php';
class CompositeCalendar {
private function blah() {
$control = new tc_calendar();
$control->stuff();
}
}
Or combine my 3 snippets to have it any other form you like.
Also I would suggest to extend the calendar if you are just building calendar class based on the the tc_calendar:
namespace GUI;
use \tc_calendar;
require_once 'tc_calendar.php';
class CompositeCalendar extends tc_calendar {
private function blah() {
$this->stuff();
}
}

Any class not in a namespace is automatically in the global namespace.
To refer to anything in the global namespace from anywhere, use a single preceding \:
new \tc_calendar;

Related

make NAMESPACE declaration conditional?

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.

PHP PSR-0 Static Class

I'm trying to rewrite an OO PHP site (that loosely follows an MVC structure) so it uses namespaces - and want to follow PSR-0.
In the current site I have a class (called APP) which is full of static methods that I call all over the place to handle things such as getting config data eg; APP::get_config('key').
Obviously with namespacing, I would need to call \TheNameSpace\App::get_config('key'). I use this class frequently, so want to avoid having to prefix the namespace every time I use it. I do call methods in it from within other classes, which would usually be under a sub-namespace - so changing the namespace at the top of the file won't really work.
So, I guess my question is, what is the easiest way to have a 'global' class with methods that I can call anywhere without having to prefix with the namespace each time?
namespace Foo;
use Bar;
Then you do not have to do \Bar\fn
So in your case:
namspace Foo;
use TheNameSpace\App;
App::get_config('blah')
Read the section in the php manual on using/aliasing namespaces.
http://www.php.net/manual/en/language.namespaces.importing.php
You can exclude the namespace by using "use". You can name it whatever you want.
use TheNamespace\App as App //You can name it anything here
App:config('key');
At top of your scripts add
use TheNameSpace\App as MyApp
for example. You can then use it like
app = new MyApp();
in your scripts. Of course you needn't to use an alias here. Just
use TheNameSpace\App
app = new App();
will work, too.
A global class that's implementing this one is bad style and you shouldn't do it like this:
class MyApp extends TheNameSpace\App { }
....
myApp = new MyApp();

How does the keyword "use" work in PHP and can I import classes with it?

I have a file with a class Resp. The path is:
C:\xampp\htdocs\One\Classes\Resp.php
And I have an index.php file in this directory:
C:\xampp\htdocs\Two\Http\index.php
In this index.php file I want to instantiate a class Resp.
$a = new Resp();
I know I can use require or include keywords to include the file with a class:
require("One\Classes\Resp.php"); // I've set the include_path correctly already ";C:\xampp\htdocs". It works.
$a = new Resp();
But I want to import classes without using require or include. I'm trying to understand how use keyword works. I tried theses steps but nothing works:
use One\Classes\Resp;
use xampp\htdocs\One\Classes\Resp;
use htdocs\One\Classes\Resp;
use One\Classes;
use htdocs\One\Classes; /* nothing works */
$a = new Resp();
It says:
Fatal error: Class 'One\Classes\Resp' not found in C:\xampp\htdocs\Two\Http\index.php
How does the keyword use work? Can I use it to import classes?
No, you can not import a class with the use keyword. You have to use include/require statement. Even if you use a PHP auto loader, still autoloader will have to use either include or require internally.
The Purpose of use keyword:
Consider a case where you have two classes with the same name; you'll find it strange, but when you are working with a big MVC structure, it happens. So if you have two classes with the same name, put them in different namespaces. Now consider when your auto loader is loading both classes (does by require), and you are about to use object of class. In this case, the compiler will get confused which class object to load among two. To help the compiler make a decision, you can use the use statement so that it can make a decision which one is going to be used on.
Nowadays major frameworks do use include or require via composer and psr
1) composer
2) PSR-4 autoloader
Going through them may help you further.
You can also use an alias to address an exact class. Suppose you've got two classes with the same name, say Mailer with two different namespaces:
namespace SMTP;
class Mailer{}
and
namespace Mailgun;
class Mailer{}
And if you want to use both Mailer classes at the same time then you can use an alias.
use SMTP\Mailer as SMTPMailer;
use Mailgun\Mailer as MailgunMailer;
Later in your code if you want to access those class objects then you can do the following:
$smtp_mailer = new SMTPMailer;
$mailgun_mailer = new MailgunMailer;
It will reference the original class.
Some may get confused that then of there are not Similar class names then there is no use of use keyword. Well, you can use __autoload($class) function which will be called automatically when use statement gets executed with the class to be used as an argument and this can help you to load the class at run-time on the fly as and when needed.
Refer this answer to know more about class autoloader.
use doesn't include anything. It just imports the specified namespace (or class) to the current scope
If you want the classes to be autoloaded - read about autoloading
Don’t overthink what a Namespace is.
Namespace is basically just a Class prefix (like directory in Operating System) to ensure the Class path uniqueness.
Also just to make things clear, the use statement is not doing anything only aliasing your Namespaces so you can use shortcuts or include Classes with the same name but different Namespace in the same file.
E.g:
// You can do this at the top of your Class
use Symfony\Component\Debug\Debug;
if ($_SERVER['APP_DEBUG']) {
// So you can utilize the Debug class it in an elegant way
Debug::enable();
// Instead of this ugly one
// \Symfony\Component\Debug\Debug::enable();
}
If you want to know how PHP Namespaces and autoloading (the old way as well as the new way with Composer) works, you can read the blog post I just wrote on this topic: https://enterprise-level-php.com/2017/12/25/the-magic-behind-autoloading-php-files-using-composer.html
You'll have to include/require the class anyway, otherwise PHP won't know about the namespace.
You don't necessary have to do it in the same file though. You can do it in a bootstrap file for example. (or use an autoloader, but that's not the topic actually)
The issue is most likely you will need to use an auto loader that will take the name of the class (break by '\' in this case) and map it to a directory structure.
You can check out this article on the autoloading functionality of PHP. There are many implementations of this type of functionality in frameworks already.
I've actually implemented one before. Here's a link.
I agree with Green, Symfony needs namespace, so why not use them ?
This is how an example controller class starts:
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class WelcomeController extends Controller { ... }
Can I use it to import classes?
You can't do it like that besides the examples above. You can also use the keyword use inside classes to import traits, like this:
trait Stuff {
private $baz = 'baz';
public function bar() {
return $this->baz;
}
}
class Cls {
use Stuff; // import traits like this
}
$foo = new Cls;
echo $foo->bar(); // spits out 'baz'
The use keyword is for aliasing in PHP and it does not import the classes. This really helps
1) When you have classes with same name in different namespaces
2) Avoid using really long class name over and over again.
Using the keyword "use" is for shortening namespace literals. You can use both with aliasing and without it. Without aliasing you must use last part of full namespace.
<?php
use foo\bar\lastPart;
$obj=new lastPart\AnyClass(); //If there's not the line above, a fatal error will be encountered.
?>
Namespace is use to define the path to a specific file containing a class e.g.
namespace album/className;
class className{
//enter class properties and methods here
}
You can then include this specific class into another php file by using the keyword "use" like this:
use album/className;
class album extends classname {
//enter class properties and methods
}
NOTE: Do not use the path to the file containing the class to be implements, extends of use to instantiate an object but only use the namespace.

Is this a good way to use Namespaces in PHP

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.

Is it bad to include all the Namespaces and access Classes with just their class name in PHP?

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.

Categories