Does PHP have some sort of using namespace of C++? (So you don't have to write any namespace before your calls)
I have defined a function within:
namespace \Project\Library {
function hello() {
}
}
Another file.php:
use \Project\Library;
hello(); //> Error: Call to undefined function hello()
PS.
I know I could use use \Project\Library as L;
And then do L\hello();
I want to avoid L\ too.
Edit
I answer myself: you cannot do it. And that sucks imo (this is the first thing I don't like of PHP).
Edit2
To be clear: If hello() was a class I could call it directly using use. The problem it is that is a simple function so I have to write its namespace. This is a little mindfucking of PHP.
Maybe we can consider this a bug and open a ticket?
Since PHP 5.3.0 it supports syntax use ... as:
use My\Full\Classname as Another
Also guessing from manual using use directly (without as Another) is not possible (it's not mentioned in manual).
You may be able to use some hack like class factory or workaround via autoloader but simple and direct answer is "it's not possible". :(
Even if PHP has namespaces and can declare functions directly outside a class, I would strongly suggest that you, at least, use static class methods. Then you don't have to hack things around and will use namespaces as they were designed to work; with classes.
Here is a working example :
hello.php
<?php
namespace Project\B;
class HelloClass {
static function hello() {
echo "Hello from hello.php!";
}
}
a.php
<?php
namespace Project\A;
require('hello.php'); // still have to require the file, unless you have an autoloader
use \Project\B\HelloClass; // import this class from this namespace
\Project\B\HelloClass::hello(); // calling it this way render the 'use' keyword obsolete
HelloClass::hello(); // or use it as it is declared
** Note **: use foo as bar; let's you rename the class! For example :
use \Project\B\HelloClass as Foo; // import this class from this namespace as Foo
Foo::hello(); // calling it this way using the 'use' keyword and alias
** Update **
Interestingly, you can do this :
c.php
namespace Project\C;
function test() {
echo "Hello from test!\n";
}
a.php
use \Project\C; // import namespace only
use \Project\C as Bar; // or rename it into a different local one
C\test(); // works
Bar\test(); // works too!
So, just write use Project\Library as L; and call L\hello();. I think it's your best option here.
Related
I have an older framework which doesn't implement namespaces. If i try to slowly introduce namespaces, by first declaring one at top of a class declaration, then any invokation of that class will now fail, because it isn't invoked through its namespace. Even though the class file is already included, and there isn't (or so i thought) a need for PHP to know the namespace.
It seems PHP doesn't care that it can find a class by the name Foo, because if Foo is under a namespace, then it will always mandate that you have to specify the namespace as well.
As a simple test, i put this in one file:
<?php
namespace Test;
class Foo {
function bar(): void {
print "Hello world.";
}
}
And this in another:
<?php
include "Foo.php";
$foo = new Foo;
$foo->bar();
It gives me the following error:
Fatal error: Uncaught Error: Class 'Foo' not found
So my question is, can this behaviour be avoided (with some configuration options maybe) to ease the slow transition from a framework that doesn't use namespaces into one that does, or would I have to replace all invokations of all the classes at once before it becomes usable? Are there any hacky alternatives?
you lost namespace :)
$foo = new \Test\Foo();
You need to provide the "path" of your class like this :
<?php
use Test\Foo;
include "foo.class.php";
$foo = new Foo;
$foo->bar();
I don't see another solution...
For more information about Use : https://www.php.net/manual/en/language.namespaces.importing.php
I'm using laravel 5.6, and in my controller I have
use RecursiveIteratorIterator;
and the error I'm getting is
Class 'App\Http\Controllers\RecursiveArrayIterator' not found
So I'm being a little simplistic about it. Obviously RecursiveIteratorIterator is not a laravel function, but rather a core php function. But after reading this post https://laraveldaily.com/how-to-use-external-classes-and-php-files-in-laravel-controller/ I'm still no clearer on where to find it, or how to reference it properly.
I suppose I was expecting that all "native" php functions would just be available?
Help?
You want to put a backslash in front (No need to put use ... at the top), to specify a root/global class:
\RecursiveIteratorIterator;
For more information, refer to the PHP documentation here:
Example #3 Accessing internal classes in namespaces
<?php
namespace foo;
$a = new \stdClass;
function test(\ArrayObject $typehintexample = null) {}
$a = \DirectoryIterator::CURRENT_AS_FILEINFO;
// extending an internal or global class
class MyException extends \Exception {}
?>
Just to be mention, it looks like you are only importing
use \RecursiveIteratorIterator;
and also calling RecursiveArrayIterator somewhere in the code. try importing both.
use \RecursiveIteratorIterator;
use \RecursiveArrayIterator;
I`m use namespace in my project. But namespace not works.
file index.php
use \Folder\Aa;
Aa::test();
$test = new Aa();
file Folder/Aa.php
namespace Folder;
class Aa
{
static function test()
{
$a = 3;
echo $a;
}
}
Write me Fatal error: Class 'Folder\Aa' not found in /home/ademidko/www/first.local/index.php
I`m changes namespace in Аа.php, write "use \Folder" and other -> but not works
PHP does not load classes dynamically by itself. In order to you to be able to use your class your code have to look like this:
require_once('Folder/Aa.php');
use \Folder\Aa;
Aa::test();
$test = new Aa();
There are many possible ways how to make this work without manually writing require or require_once. One of them is to use composer's autoloading functionality (details can be found here: https://getcomposer.org/doc/04-schema.md#psr-4).
You can also consider writing your own autoloader (more details here: http://php.net/manual/en/function.spl-autoload-register.php)
I just wonder if there's a way to make a class behave as if it is in global namespace using a "use" keyword, so this class would behave as namespaced class only from outside of the class.
Something like:
namespace wherever\somewhere\deep\deep\inside;
use \; // root namespace.. note: this doesn't work
class stuff{
//....
}
anyone?
Using the global namespace won't work the way you expect.
By default, you can reference a globally namespaced class by adding a backslash -- eg $x = new \PDO(...);. Trying to use \ won't change that.
If you want to drop the backslash from globally namespaced classes, you need to use each of them specifically. In namespaced PHP, any class reference that doesn't have a namespace is assumed to be in the current namespace, unless it is explicitly referenced by a use statement.
eg:
use \PDO, \SplFileObject;
now we can call new PDO(...) or new SplFileObject() without the backslash. But other global classes that aren't in the use would still need the backslash.
You can access the global namespace if you use brackets like this:
namespace My\Space {
function myScopedFunction() { .. }
}
namespace {
function myGlobalFunction() { .. }
}
I don't think you can. If anyone finds a good way please do share.
I tried the below which didn't work obviously (the writeup is here http://www.siteconsortium.com/h/D0000H.php). I would find it really useful to be able to go to the root namespace this way as a lot of legacy code doesn't use namespaces.
$root = \_\_NAMESPACE\_\_; // error
namespace AA;
function foo() { print " What AA "; }
use ($root); // error
namespace $root; // error can't use var
namespace ""; // error
use "/"; // error
namespace "/"; // error
There are a couple different issues here. One thing I thought was strange is that I can use the keyword require_once $script_name but I can't use the keyword namespace $namespace_name.
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.