I read an article about namespaces in PHP. But I don't get what they are used for?
<?php
namespace MyProject {
// Regular PHP code goes here, anything goes!
function run()
{
echo 'Running from a namespace!';
}
}
I also read the PHP.net manual about it, but didn't quite get it.
I had a tough time as well, just think of it as a way to help the compiler resolve names.
So there is no ambiguity.
You could have two developers writing completely different classes but with same type identifier.
The class names could be the same. Grouping in namespaces helps the compiler/interpreter will remove the ambiguity.
So namespace Developer1.CoolClass is quite different from namespace Developer2.CoolClass
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.
PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants.
Check Here for details
Namespaces are a way to group your related classes in packages.You can assume namespaces as folders where you keep your files,in a way that both can have the files with same name but different (or same) without any ambiguity.
file1.php
<?php
namespace Foo\Bar\subnamespace;
const FOO = 1;
function foo() {}
class foo
{
static function staticmethod() {}
}
?>
file2.php
<?php
namespace Foo\Bar;
include 'file1.php';
const FOO = 2;
function foo() {}
class foo
{
static function staticmethod() {}
}
/* Unqualified name */
foo(); // resolves to function Foo\Bar\foo
foo::staticmethod(); // resolves to class Foo\Bar\foo, method staticmethod
echo FOO; // resolves to constant Foo\Bar\FOO
/* Qualified name */
subnamespace\foo(); // resolves to function Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // resolves to class Foo\Bar\subnamespace\foo,
// method staticmethod
echo subnamespace\FOO; // resolves to constant Foo\Bar\subnamespace\FOO
/* Fully qualified name */
\Foo\Bar\foo(); // resolves to function Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // resolves to class Foo\Bar\foo, method staticmethod
echo \Foo\Bar\FOO; // resolves to constant Foo\Bar\FOO
?>
Consider your write your own class, lets called it Foo. Someone else writes also a part of the project and he calls one of his classes also Foo.
Namespaces solve this problem.
Example:
Namespace MyClasses;
Class Foo
{
}
NameSpace HisClasses;
Class Foo
{
}
$myfoo = new MyClasses\Foo();
$hisfoo = new HisClasses\Foo();
Namespaces are used to isolate functions and class declarations in order to make libraries and "helpers" (files containing functions) more portable. By putting a library in a name space, you reduce the chances of your class names colliding with what an author who may want to use your library may want to call their classes For example, you can have multiple classes named "user" if they're in separate namespaces.
Related
I want to know if there is a way to namespace values, in a similar way that we namespace functions in PHP.
You can have:
namespace pizza\land;
function turn_oven_on(){}
And you can access that function with pizza\land\hello()
I wonder if there is a way to do something similar for values.
This is not correct, I am just illustrating what I mean:
namespace pizza\land;
namespaced $ingredients = array('pepperoni', 'garlic');
Then access it with $pizza\land\ingredients.
Other parts in the same runtime can do:
namespace pasta\land;
namespaced $ingredients = array('tomato', 'mozzarella');
Then access it with $pasta\land\ingredients.
Of course that doesn't work, but it serves as an example of what I mean.
I know there is the obvious way, which would be to use the Singleton pattern where the constructor sets the value of a public property for the singleton instance (the one and only one instance of the class).
I dislike this setup, and in that case I prefer to go the killer route and just do global $pseudonamespaced_pizza_land_ingredients.
I wonder, is there anything else I can do to achieve this setup using the latest version of PHP (now 8.1)?
Why?
To have the same effect you have with global but at the same time avoid collision.
Well, let's say I am working with some procedural code and I need a value that can be accessed across multiple functions.
So I want to use that value within the realms of that bunch of functions.
I do not want to wrap all those functions into one Class and then use a property for that class, because in that case I just prefer the Singleton or the global.
Also, if not possible. Why not?
I cannot believe that this hasn't been mentioned before as something to consider for integration into PHP. So, there must be a reason for this not being possible, if it isn't. It would be a cool solution for all those codebases that are mostly procedural and use global way too often... ehem... WordPress...
I think this could be a good answer for this question as the goal is to have variable live inside of the namespace, and that OP has overcomplicated the question for no reason.
Assuming that you have a variable named $number in the global scope of a PHP script. Inside a function, we have another variable with the same name $number, and we assign and change values of it within the function. But, the global variable remains unchanged. This is variable scope. In the same way, classes can be namespaced to give it scope.
Consider having a following code:
<?php
namespace Math;
function add($a, $b) {
return $a + $b;
}
const PI = 3.14;
class Geometry {
static function getCircleArea($radius) {
return PI * $radius ** 2;
}
}
First, we declare the namespace. (So, all the classes, interfaces, constants and function below it will be items of that namespace)
Then, we declared a normal function.
Then, a class constant.
Then, a class.
Now let's access to theseMath namespace's items from another file(functions, constants, and classes).
<?php
// includes the Math.php file
// It's like you had all the code of Math.php written here
include_once 'Math.php';
echo Math\add(2,3); // 5
echo Math\PI; // 3.14
echo Math\Geometry::getCircleArea(10); // 314.15
Thanks to #shingo's comment under the question, this is how I now learned that this can be achieved.
// Namespace
namespace whatever;
// Class with static property
class StaticStuff {
static string $variable = 'Hey';
}
// Access it
echo StaticStuff::$variable; // Hey
// Edit it
StaticStuff::$variable = 'Miau!';
// Access it again
echo StaticStuff::$variable; // Miau!
Specifically:
Define a class
With a static property
Inside a namespace
I'm trying to figure out how namespaces work in PHP but have a hard time understanding when a global namespace prefix is required. Take the following example:
index.php
namespace MySpace;
require_once 'file.php';
Test::hello();
hi();
file.php
class Test {
public static function hello () {
echo 'hello';
}
}
function hi() {
echo 'hi';
}
This won't work but writing \Test::hello() instead will and echoes both "hello" and "hi".
Why isn't the \ required for hi() as well?
http://php.net/manual/en/language.namespaces.fallback.php
Using namespaces: fallback to global function/constant
Inside a namespace, when PHP encounters an unqualified Name in a class
name, function or constant context, it resolves these with different
priorities. Class names always resolve to the current namespace name.
Thus to access internal or non-namespaced user classes, one must refer
to them with their fully qualified Name [...]
For functions and constants, PHP will fall back to global functions or
constants if a namespaces function or constant does not exist.
If you try using class_exists() inside a method of a class in PHP you have to specify the full name of the class--the current namespace is not respected. For example if my class is:
<?
namespace Foo;
class Bar{
public function doesBooClassExist(){
return class_exists('Boo');
}
}
And Boo is a class (which properly autoloads) and looks like this
namespace Foo;
class Boo{
// stuff in here
}
if I try:
$bar = new Bar();
$success = $bar->doesBooClassExist();
var_dump($success);
you'll get a false... is there an alternative way to do this without having to explicitly specify the full class name ( i.e. class_exits('Foo\Boo') )?
Prior to 5.5, the best way to do this is to always use the fully qualified class name:
public function doesBooClassExist() {
return class_exists('Foo\Boo');
}
It's not difficult, and it makes it absolutely clear what you're referring to. Remember, you should be going for readability. Namespace imports are handy for writing, but make reading confusing (because you need to keep in mind the current namespace and any imports when reading code).
However, in 5.5, there's a new construct coming:
public function doesBooClassExist() {
return class_exists(Boo::class);
}
The class pseudo magic constant can be put onto any identifier and it will return the fully qualified class name that it will resolve to.......
I'll try to describe the situation I'm having problems with:
I have one main folder. I keep all files in there (empty classes for a reason), and one sub-folder, containing the same files, with all implementations here (empty classes extend them).
the main folder's namespace is declared as Project/Folder, and the sub-folder as Project/Folder/Subfolder. These are class's declarations:
namespace Project\Folder;
class Foo extends Subfolder\Foo { }
namespace Project\Folder\Subfolder;
class Foo { }
What I want to achieve is to be able to call other classes from inside of the Project\Folder\Subfolder\Foo through these empty classes on the lower level, with only its name, e.g.:
namespace Project\Folder\Subfolder;
class Foo {
function bar() {
Another_Class::do_something();
}
}
By default, there will be called Another_Class from the Project\Folder\Subfolder namespace. I want this to refer to Another_Class from the Project\Folder namespace with the same syntax - is that possible?
I hope I explained this clear enough, if not, write a commend, and I'll try to make it clearer.
You can achieve that using the use statement.
use Project\Folder\Subfolder\Another_Class as SomeAlias;
// ...
SomeAlias::doSomething();
// or
$object = new SomeAlias();
$object->doSomething();
Alternatively, you would have to reference the entire namespace:
\Project\Folder\Subfolder\Another_Class::doSomething();
// or
$object = new \Project\Folder\Subfolder\Another_Class();
$object->doSomething();
More information here.
I always thought the main goal of a namespace is to prevent name collision and ambiguity.
#1 problem fixed by namespaces from php.net:
Name collisions between code you create, and internal PHP
classes/functions/constants or third-party
classes/functions/constants.
However, most languages implement the "use" keyword in some way to alias or import other namespace to the current one. I know how it works, but I don't understand why such functionality is ever used.
Isn't using a 'use' keyword effectively defeating the purpose of a namespace?
namespace core\utils;
class User {
public static function hello(){
return "Hello from core!";
}
}
//---------------------------------------------------
namespace core2\utils;
class User {
public static function hello(){
return "Hello from core2!";
}
}
//---------------------------------------------------
namespace core2;
//causes name collision, we now have two different classes of type 'utils\User'
use core\utils; //without this line the result is 'Hello from core2'
class Main {
public static function main(){
echo utils\User::hello();
}
}
Main::main();
//outputs Hello from core!
?>
Am i missing something or is usage of 'use' keywords really generally discouraged?
Either way, under what circumstances is it actually a good idea to sacrifice the encapsulation?
I used to use use, but now I am not sure when use should be used.
Edit: Alright let me get this straight: If I use 'use' to get short name, how is that better than just declaring the class in global namespace? See below:
namespace core\utils\longname {
class User {} //declare our class in some namespace
}
//------------------Other File---------------------------
namespace { //in another file import our long name ns and use the class
use core\utils\longname\User as User;
new User();
}
^ What is the advantage of namespacing like that against this declaration:
namespace {
class User {} //declare our class in global namespace
}
//------------------Other File---------------------------
namespace { //in another file just use the class
new User();
}
Is there any difference at all between the two?
+1 Very Interesting question
My Opinion
The keyword use as so many uses and functionality imagine this
use core\utils\sms\gateway\clickatell\http\SmsSender as SmsCSender
use core\utils\sms\gateway\fastSMS\ftp\Smssender as SmsFSender
Now Compare
if(!SmsCSender::send($sms))
{
SmsFSender::send($sms);
}
To
if(!core\utils\sms\gateway\clickatell\http\SmsSender::send($sms))
{
core\utils\sms\gateway\fastSMS\ftp\SmsSender::send($sms);
}
Conclusion
Without namespace and use i would not be able to achieve such a clean readable code so what i think is that namespace and use complement each other rather than 'use' defeating the purpose of a namespace