So I'm targetting my compiler to PHP and I'm having some problems with namespaces.
They look something like this in my language:
package Foo
{
package Bar
{
class X { }
}
class Y { }
}
Of course, PHP doesn't handle nested namespaces. What's the best way to translate this code so it still works in PHP?
I should note that all files are compiled into a single PHP file in the end. One caveat of this is that I'll have to go back to the global namespace after I've closed a package, and I haven't found any documentation about how to do that. It seems to me that in PHP, once you declare a namespace, it applies to the whole file.
It's true that "Namespace declarations cannot be nested".Namespacing is used to avoid conflicting definitions and introduce more flexibility and organization in your code.The brackets surrounding the namespace code block are completely optional.If you want to translate your code to run able in php. You can write like:
namespace Foo\Bar;
class X{
// Your properties
}
class Y {
// Your properties
}
If you need more information you can see this link well written by Elias Zerrouq with example http://code.tutsplus.com/tutorials/namespacing-in-php--net-27203
Zotoaster it is quite possible to do what you desire; however, my solution would rely on the psr-4 autoloading solution. With this, by placing your files in the appropriate folders, you would be able to do the following at the start of the php file:
use Foo\Bar\X;
use Foo\Y;
Thereafter you can instantiate the classes accordingly:
$x = new X();
$y = new Y();
You can read more on how to use namespaces here: http://www.php-fig.org/psr/psr-4/
Furthermore, you could use composer to handle the "dirty work" for you, i.e. all the auto loading: https://getcomposer.org/doc/01-basic-usage.md#autoloading
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 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.
I'm currently reading Modern PHP Book and I'm a little confused since in Chapter 2 the author talks about Namespace and he keeps saying import when he refers to the "use". In fact he states the following...
TIP
You should import code with the use keyword at the top
of each PHP file, immediately after the opening <?php tag or...
The way I understand Namespace is that the use keyword references the namespace of the class but it doesn't import it and you still need to use require or include to import the actual class, correct?
I'm I correct when I say that when using namespace without auto-loading you will need to use require or include to import your classes?
Thanks
If you use autoloader, such as composer, you do not need to import or require PHP files (you only load autoloader file, which actually does all that for you). If you have no autoloader, you have to load files using import or require.
Then, after FILE is loaded, you can use use statements to do actual work with name-spaced items, such as classes, interfaces or traits.
Yes, you're correct. The use keyword in PHP merely aliases a namespace, in that it does what a symlink (on a *nix system) or shortcut (on a Windows system) would.
If you read the manual about PHP namespace basics you'll see that namespaces can be analogous to a filesystem where class/interface/constant/function names can be divided up into folders in order to prevent name-clashes.
If you read the manual section on Namespace Importing you'll see that when we refer to importing in PHP it actually means to create a shortcut of one name to another name (in fact the shortcut analogy above is taken right from the manual)...
This is similar to the ability of unix-based filesystems to create symbolic links to a file or to a directory.
So, while confusing, the use keyword in PHP does not attempt to load (or include) the actual file containing the namespace, but rather just creates an alias for given namespace(s).
This may be very different use of the word import than you may be used to in other languages, where import can mean to load the actual file or package, but in PHP it's important to understand that importing a namespace has nothing to do with autoloading or including files. They are two separate concepts in PHP.
Importing a namespace is so that you can refer to \fully\qualified\namespace\MyClass as simply MyClass inside your namespace rather than having to use the FQN every single time (hence the shortcut analogy).
Autoloading, is for including the actual classes in PHP when they get used in code.
So there's a definite disconnect between the two concepts.
Since you mentioned a Chapter 2 in a book, I'm going to assume that you are still learning PHP, yes?
The use of use is to shorten namespaced classes to their root so that if you have some long namespaced class like
org\shared\axel\web\framework\connection\pipeline\impl\StopExecutionException
that needs to be instantiated with
new org\shared\axel\web\framework\connection\pipeline\impl\StopExecutionException();
You can use use to refer only to the root unnamespaced class
use org\shared\axel\web\framework\connection\pipeline\impl\StopExecutionException;
...
throw new StopExecutionException();
Keep in mind that you still need to have the class's code in your script, so you either include/require that manually by using include or require, or register autoloaders (see spl_autoload_register).
What that does is you define how your namespace maps to your source code's directory structure.
What others here refer to as composer is a package manager that includes an autoloader. At this stage, I personally think it's better to put off learning about this until you have a good grasp of the basics.
If you have an autoloader then use can be used to pull a Trait
Trait file
namespace Blah;
Trait Foo {
protected $somevar;
}
Class file
Class Bar {
use \Blah\Foo; // autoloaded
}
Otherwise, use is used to indicate that you want to either load a given class or alias that class as another
Class Foo {
}
use \Foo as Bar;
Class Something extends Bar {
}
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;
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.