I am builded a new object in my file without namespaces:
new My\Validator();
Above, in the same file I have got __autoload():
function __autoload($className)
{
var_dump($className);
}
The __autoload() function prints
'My\My\Validator'.
Where is the double 'My' come from?
It is adding the My namespace because you are probably inside the My namespace already when you create the object with new My\Validator().
namespace My;
$obj = new My\Validator();
will be translated to:
$obj = new My\My\Validator();
Since you are inside the My namespace already you can:
either just call new Validator()
or call new \My\Validator()
The beginning \ will tell PHP to look into the global namespace.
On a side note, it is considere good practice to use spl_autoload_register instead of __autoload, because you can set multiple autoloader callbacks.
Related
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 am working on the AWS documentation which uses Guzzle framework. I have to deal with namespaces here and I am not able to get it working. I went through the docs and examples and understood that we can have packages for projects using namespaces.
I went ahead and tried a simple example, but unsuccessful. Here's the example: this is the index.php:
use My\Full\Classname as Another; //Also tried use My\Full\Classname
$obj = new Another; //with $obj = new Classname;
echo $obj->add();
I have Classname.php in the directory structure like this My->Full->Classname.php:
<?php
class Classname{
public static function add(){
return 2+2;
}
}
?>
I am trying to call the function in index.php but getting error:
Fatal error: Class 'Another' not found in C:\wamp\www\guzzleEx\index.php on line 19
which is the line where I instantiate the Classname object $obj = new Another;
What is the mistake i am making? Is there any INI that needs to be updated or any other config issue? How can I make the code working? If you use the normal include for Classname.php it works fine.
Namespaces need to be explicitly declared, they do not come from a certain directory structure.
So if you do not have a line that reads namespace My\Full; in front of your class Classname, then your class is not in any namespace, but in the root namespace.
Thus you cannot use it as \My\Full\Classname, but \Classname or even Classname directly.
what is/are the benefit(s) of having multiple spl_autoload_register
example:
spl_autoload_register('autoload_systems');
spl_autoload_register('autoload_thirdparties');
spl_autoload_register('autoload_services');
vs:
using one
spl_autoload_register('autoload'); or __autoload();
and then do the logic inside the function.
eg:
$ftp = new systems_ftp();
$services = new services_cron_email();
If you have one __autoload() and you include a third party library which also had one, it would be clobbered.
Registering multiple autoloads with spl_autoload_register() ensures you can have your code dropped in with existing code (think libraries, etc) without clobbering or shadowing of existing/future autoloads.
In addition, the PHP manual states...
spl_autoload_register() provides a more flexible alternative for
autoloading classes. For this reason, using __autoload() is
discouraged and may be deprecated or removed in the future.
I guess no need to add multiple but it's on your logic.
The way spl_autoload_register works is awesome.
Suppose one have 3rd parties directories and that is usually manages through namespace which also represents their path.
Consider this simple class as autoloader class
class MyAutoLoader {
public function __construct()
{
spl_autoload_register( array($this, 'load') );
}
function load( $class )
{
$filepath = 'classes/'.$class.'.php';
require_once( $filepath);
}
}
Then in index file include this loader file and create instance of this class:
$autoload = new MyAutoLoader();
Now you can directly create the instances of classes.
Suppose we have 'Person' class in directory classes\QMS\SERVICES\Person.php and same path is the namespace of that class
$person = new QMS\SERVICES\Person();
Now when when you will use new it will check if this class exists and value as a string will be passes to 'load' function of class 'MyAutoLoader'. and there it will get included. Or you can change the function 'load' to fix the path of your class files put your if conditions or whatever need to b done to fix the paths.
I can't get dynamic instantiating of classes in PHP to work when my files are namespaced.
PHP seems to be completely ignorant of the use keywords on top of my files, as I try to instantiate classes dynamically based upon the value of a variable.
Is there a good solution to this, besides hardcoding the namespace when dynamically instantiating classes?
Here's some quick samples to show what I mean:
Code new two('one'); results in that the class one isn't found with the below two files being included:
File1:
namespace uno;
use dos;
class one {
function __construct($what) {
new $what;
}
}
File2:
namespace dos;
class two { }
File 3:
new one('two'); // Doesn't work!
Either full-qualified
new \uno\one('two');
or defined by use
use uno\one;
new one('two');
or (relative) qualified (but that makes not much sense with a one-level namespace)
use uno;
new uno\one('two');
With deeper namespace it makes more sense
use path\to\myNamespace;
new myNamespace\foo\BarClass;
or put it in the same namespace
namespace uno;
new one('two');
See http://php.net/language.namespaces.rules