This is my project path configuration
./create.php
/Install/Install.php
create.php
<?php
use Install\Install;
echo "Starting";
$install = new Install();
This gives me the error
PHP Fatal error: Uncaught Error: Class 'Install\Install' not found in /project/create.php:6
Install.php
<?php
namespace Install;
class Install
{
//whatever
}
Can someone explain me what is happening there ?
Obviously I guess that using a require_once line with my filename would probably fix the issue...but I thought using namespace and use import could prevent me from doing that like we do in classic framework like symfony / magento ?
I've seen some post speaking about autoloading, but i'm a little bit lost. Haven't been able to find a clear explanation on the other stack topic neither.
PHP compiles code one file at a time. It doesn't have any native concept of a "project" or a "full program".
There are three concepts involved here, which complement rather than replacing each other:
Namespaces are just a way of naming things. They allow you to have two classes called Install and still tell the difference between them. The use statement just tells the compiler (within one file) which of those classes you want when you write Install. The PHP manual has a chapter on namespaces which goes into more detail on all of this.
Require and include are the only mechanisms that allow code in one file to reference code in another. At some point, you need to tell the compiler to load "Install.php".
Autoloading is a way for PHP to ask your code which file it should load, when you mention a class it hasn't seen the definition for yet. The first time a class name is encountered, any function registered with spl_autoload_register will be called with that class name, and then has a chance to run include/require to load the definition. There is a fairly brief overview of autoloading in the PHP manual.
So, in your example:
use Install\Install; just means "when I write Install, I really mean Install\Install"
new Install() is translated by the compiler to new Install\Install()
the class Install\Install hasn't been defined; if an autoload function has been registered, it will be called, with the string "Install\Install" as input
that autoload function can then look at that class name, and run require_once __DIR__ . '/some/path/Install.php';
You can write the autoload function yourself, or you can use an "off-the-shelf" implementation where you just have to configure the directory where your classes are, and then follow a convention for how to name them.
If you want to Use class from another file, you must include or require the file.
Use require('Install.php'); before use Install\Install;.
If you are planning to do a big project I would recommend to use PHP frameworks rather than coding from scratch.
Related
This is what I have at hand:
//Person.php
namespace Entity;
class Person{
}
User file:
//User.php
use Entity\Person;
$person = new Person;
Here, it fails if I don't include the Person.php file. If I include it, the everything works fine. Do I absolutely require to include the file even when using namespaces? If at all we need to include/require files, then how can namespaces be effectively used? Also, can we maintain folder structure by nesting namespaces?
The answer to your question is "yes and no".
Indeed the code implementing class Person has to be included, otherwise the class is not defined and cannot be used. Where should the definition come from, when the code is not included? The php interpreter cannot guess the classes implementation. That is the same in all programming languages, by the way.
However there is something called Autoloading in php. It allows to automatically include certain files. The mechanism is based on a mapping of class names to file names. So in the end it boils down to php searching through a folder structure to find a file whos name suggests that it implements a class currently required in the code it executes.
But don't get this wrong: that still means the file has to be included. The only difference is: the including is done automatically, so without you specifying an explicit include or require statement.
Yes, you need to include every file.
A very good example can be found here on effective usage of namespaces.
With PSR-0 autoloading, the namespace has to be the same as the folder in which the class is, file the filename has to be the same as the classname. This gives you very simple and effective autoloading with composer for example.
I've seen a lot of threads here and in other forums that asked this a lot of times, but I still see using the include function of PHP in the answers?
how can I use this function, not using totally the include function?
Thank you
how can I use this function, not using totally the include function
You cannot totally not use include and that is not the point of using autoloader as you usually need to at least include the autoloader ;). That autoloader is the regular PHP code that is being called by PHP when unknown class use is attempted in the code. It is expected to include right file to make the class known, and the code continues as you'd explicitely include right file by hand in your code. So the main benefit shows up when your code uses classed (OOP) - you do not need to care if you included the class you are about to instantiate the object of or not. You just do new Foo() or call Something::methodName() and if all is set up right it will work.
The function spl_autoload_register is used to register a callback into the autoloader queue.
The PHP autoloader is a functionality of the PHP interpreter that, when a class is not defined, calls the functions registered in the queue, one by one, asking them to load the class, until the class becomes available. It the class is still not available after all the functions were invoked, the interpreter triggers a fatal error.
The autoloader doesn't perform any magic. It is the entire responsibility of the registered functions to make the class available. Most of them use the name and namespace of the missing class to figure out the path of the file that contains the declaration of the class and include it.
That's how the thing works. There are not many ways to produce a class in PHP and, for a reusable autoloader callback, the list starts and ends with include1 (include_once, require or require_once can be used as well but they don't make any difference in this case.)
The autoloader callback itself stays in separate file (for reusability) and usually that file also contains its registration as autoloader callback (the call to spl_autoload_register). All your code have to do is to include this file once in every file that is an entry point of your application.
All things being equal, your application needs to use include at least once and once is also the maximum required number of usages for it. The autoloader callback also uses include (probably also only once) but you don't write autoloader callbacks every day. If you wrote one and you wrote it well you can reuse it. Most people never wrote an autoloader callback and they will never write one.
Using Composer is easy and if you follow the PSR-4 rules of naming the files of your project, Composer can generate an autoloader for your project that knows how to load your classes (behind the scene it uses include, of course). All you have to do is to run composer init in the root directory of your project, run composer install and write include 'vendor/autoload.php'; in the file that represents the entry-point of your application. No other uses of include are required.
1 An autoloader callback is not required to include another file to make the class available. It can generate the code of the class on the fly and eval()-uate it, but the use cases of such approach are very limited. It is used by the testing suites f.e., to generate mock classes.
I am using Vzaar's PHP Library for uploading videos from my website to their server space.
Now point is - in their library there are some PHP files in which more than one class exists and no class with same file name exists in same file.
i.e. have a look at OAuth.php, there is no class with name OAuth in that file.
Question raised in my mind is
When I create any PHP class file, can I create multiple classes in side one file, and later I can use that file in my code or I can use that reusable code in other project as well.
Should creating such files is good practice?
If the class is of 15 to 20 lines long, then should I create a separate file or I should include that in one file only, like OAuth.php.
Please guide with exact reason, if I will get links of wiki where proper explanation is given, then it will be best.
Putting more than one class in one file in general is a bad practice, and in Symfony2 even more because of the way class autoloader works.
When autoloader is looking for Acme\DemoBundle\SomeClass class it expects it will be in Acme\DemoBundle\SomeClass.php file. So in case you have a second class in the same file it won't work.
Check also PSR standards for class autoloading.
Despite I don't like to define more than one class per file I would like to point it out that PSR-4 is not against this practice if the class scope is private.
Quoting Symfony2 coding standards resource (http://symfony.com/doc/current/contributing/code/standards.html)
Define one class per file - this does not apply to private helper
classes that are not intended to be instantiated from the outside and
thus are not concerned by the PSR-0 and PSR-4 autoload standards;
In this other example (Thanks to Xavi Montero) you can see that the class Psr4AutoloaderClassTest has a helper class MockPsr4AutoloaderClass defined in the same file. So in general you should not, but for a "private helper" it's okey.
https://www.php-fig.org/psr/psr-4/examples
Is it common practice to append use '.class.php' extension for PHP classes?
On PHP.net here: http://php.net/manual/en/function.spl-autoload-register.php there are some examples like this:
// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($class) {
include 'classes/' . $class . '.class.php';
});
which use a .class.php extension.
Should PHP code be written like this? I've never seen it before, is it something new? This is a kind of new feature in PHP so maybe it is?
EDIT: 'feature' was not a good word! Perhaps I should have asked whether it's some standard or convention.
Thanks.
It's not a feature, it's just a convention that you see come up every now and then. Whether to follow it or not is the choice of you and your team.
My personal opinion is that since the choice is arbitrary and this particular style contradicts with the PSR-0 autoloader specification you should pass because:
PSR-0 is more widely used, so all other things being equal it would be a better convention to follow
following the ".class.php" style means cannot take a PSR-0 compliant autoloader (there are many online) and use it without modifications
This is mostly used to assure its a class file the autoloader targets, you often have other .php files like templates, scripts like bootstrapping or config files that are .php files, but should never be interpreted as classes
It's not a feature as such, it's just a very simple, and practical way to keep your code organized and, more importantly, to avoid issues with autoloading.
Suppose you've got some class called User, and your site has a page, that is generated by a script: User.php. If you need an instance of the User class, the autoloader function will be called, and get User as an argument. When looking for a file simply called User.php, you might include a file, other than the class definition. That's why you can (and should) give class definition a little extra in their names. Then you can write your autoloader to look for [[class name]].class.php, neatly avoiding the User.php file.
That's the bottom line of it. There's -of course- also namespaces to consider, and that most modern way of all to keep your code organized: directories (set_include_path)
It is all for better understanding what this files all about. So, when you see filename.class.php, you know, this file contains Class filename.
There isn't any kind of special language support that gets triggered if you name your classes 'class.php'; it's just a convention, like whether you use spaces or tabs for indentation.
In one of the projects I worked on, classes where named *.inc.php, and templates *.tpl.php.
If I was coding php circa 1999, this would be an excellent convention to follow. You can name files whatever you want, but I recommend just naming them after the classname inside the file, with '.php' appended.
This is more of a personal preferences, but I would actually probably look into the PSR-0 standards which provide a standard way for you to name and namespace your classes to provide better compatibility with other peoples code in the same format.
In the PSR-0 standards PHP files are named after the class and put into folders related to the namespace.
I would recommend adopting this method over the .class.php method mentioned in the PHP.net manual.
I have two PHP apps which have twho class with the same name.
- app1 with a class "Project"
- app2 with a class "Project"
I have to use classes of the first app in the second one, but two class with one name cause an error ("PHP Fatal error: Cannot redeclare class Project ...").
I can't change class names.
I have to use PHP 5.2 (no namespace in PHP 5.2).
Is there a solution ?
May be :
use the class Project
undef this class (kind of "unset Project", is it possible with PHP ?)
include() the 2nd class
use the 2nd class
I don't know if it's possible with PHP (don't find any ressource about this) and I don't know a better way to manage this ...
I had this problem recently, with (embarrassingly) Joomla. I needed to find the versions of two different installations with one script, by loading up their two "version.php" files and then reading the class properties. But, of course, they're both called "JVersion", and it's impossible to require() both version.php files because of it.
After much thought, I realized eval() could take the place of require(). So I just read in the contents of the version.php files and change the names of the classes, then eval() that text, and then I can access both classes with different names. I bet you'd like some code. Here's what I ended up with...
$v15_txt=file_get_contents($old_dir.'/libraries/joomla/version.php');
$v15_txt=preg_replace('/class JVersion/i', 'class JVersion15', $v15_txt);
eval('?>'.$v15_txt);
$jvold=new JVersion15;
$old_version = $jvold->RELEASE.'.'.$jvold->DEV_LEVEL;
$v25_txt=file_get_contents($new_dir.'/libraries/cms/version/version.php');
$v25_txt=preg_replace('/class JVersion/i', 'class JVersion25', $v25_txt);
eval('?>'.$v25_txt);
$jvnew=new JVersion25;
$new_version = $jvnew->RELEASE.'.'.$jvnew->DEV_LEVEL;
Just modify it so it loads the right two files for your needs and renames them as required. Sorry you had to wait over a year for it. :-)
It's hard to believe PHP doesn't have some kind of "undeclare($classname)" function built-in. I couldn't even solve this with namespacing, because that requires changing the original two files. Sometimes ya just gotta think outside the framework.
Stop.
Whatever you are doing is wrong. Backup. Re-evaluate what you are doing and why.
If after that, you still need to do this. Pick an app, and do a find and replace on that class name in the app. If it was well designed, it should be unique and easy to do.
Document the hell out of the fact that you did this in whatever external documentation you are using.