PHP: Is AutoLoader able to load multiple class in a single php file?
Asked Answered
S

4

7

Quote from Autoloading Classes :

Many developers writing object-oriented applications create one PHP source file per class definition. One of the biggest annoyances is having to write a long list of needed includes at the beginning of each script (one for each class).

In PHP 5, this is no longer necessary. The spl_autoload_register() function registers any number of autoloaders, enabling for classes and interfaces to be automatically loaded if they are currently not defined. By registering autoloaders, PHP is given a last chance to load the class or interface before it fails with an error.

Here comes the question, what if there are multiple classes in a single php file, is it suitable for autoload usage? or do I have to use require filepath statement?

For example, I have a protocol file under Protobuf\Client.php:

<?php

namespace Protobuf;
class A {
...
}
class B {
...
}
Stowell answered 23/6, 2016 at 3:50 Comment(5)
You would have to have some complex function to autoload those classes from the file named Client.php. The idea is to translate your namespace\classname into a directory\filename.phpBlackington
In this instance you would need to name your file A.php then when you call new Protobuf\A() it will find it. Otherwise you will have to create a overly-complex autoloader.Blackington
Finally, if you do create it so the autoloader finds the A class, then you can have B on the same file, but only if you have already autoloaded A otherwise you have to make some algorythm to know that A and B are on the same page.Blackington
@Rasclatt, "copy paste" your three comments as an answer, you are correct.Blackandwhite
@P0lT10n Yeah, I probably should. It was a rolling thought that I kept elaborating on...sort of got long winded.Blackington
B
3

You would have to have some complex function to autoload those classes from the file named Client.php. The idea is to translate your namespace\classname into a directory\filename.php

In this instance you would need to name your file A.php then when you call new Protobuf\A() it will find it. Otherwise you will have to create an overly-complex autoloader.

Let's say you do create the autoloader so it finds the A class, then you can have B on the same file, but only if you have already autoloaded A otherwise you have to make some algorythm to know that A and B are on the same page.

I would do the above pattern or the pattern adopted by apps like Magento that turn class names into directory paths by replacing underscores:

$class = new Core_Classes_MyClass_Client();

Your autoloader would replace the underscores and will load:

Core/Classes/MyClass/Client.php //or similar scheme

This to me is an easy way to do it, but I prefer using namespace and class. The above method is not in favor at the moment and from a naming standpoint, very easy to get mixed up since a lot of classes may be in the same folder or nested really deep into sub folders. You could get some really long naming for classes.

Blackington answered 23/6, 2016 at 4:12 Comment(3)
psr-0 namespacing ftw.Moussaka
I can add to this answer, that the best approach is to have every class in a single file, so the autoloader (as described by author's answer) will find any class you are calling by the namespace\classname conventionBlackandwhite
I'm very glad to find such informative discussion. Thank you all guys!Stowell
I
3

To answer this question directly, we can use classmap for autoload in composer.json to support the single file containing multiple class.

For example we are going to support the single file Protobuf\Client.php, which has two class A and B in it:

<?php

namespace Protobuf;

class A {
}

class B {
}

We add classmap in the composer.json as following:

{
    "name": "hailong/myproj",
    "autoload": {
        "classmap": [
            "Protobuf/Client.php"
        ]
    }
}

Then, in main.php we can use class A and B:

<?php

require __DIR__.'/vendor/autoload.php';

use Protobuf\A;
use Protobuf\B;

$a = new A();

$b = new B();

Finally, don't forget to run composer dump-autoload after changing the composer.json, which will magically generate the autoload.php that required in our main.php.

For people not quit familiar with the composer yet, here is the final files structure we will get:

myproj % tree
.
├── Protobuf
│   └── Client.php
├── composer.json
├── main.php
└── vendor
    ├── autoload.php
    └── composer
        ├── ClassLoader.php
        ├── LICENSE
        ├── autoload_classmap.php
        ├── autoload_namespaces.php
        ├── autoload_psr4.php
        ├── autoload_real.php
        ├── autoload_static.php
        └── installed.json

3 directories, 12 files
Indubitable answered 7/5, 2020 at 21:37 Comment(0)
M
1

To extend on Rasclatts very informative answer,

Ideally, it's always good practice to separate classes when it comes to autoloading. I strongly recommend looking into composers PSR-0 Namespace Autoloading

PSR-0 Allows you to beautifully organise all your classes into sub folders with infinite depth, take the following folder structure

\system
 - Members
     - Members.php
 - Auth
     - Auth.php
 - Database
     - Database.php

For this example, in each of the php files above you would have namespace MyNameSpace; before your class declaration and then in your composer.json you would have something similar to (documentation):

"autoload": {
    "psr-0": { "MyNameSpace": "/system" }
}

Composer should be installed on your local/host computer for you to compile your autoload files, open terminal and navigate to your project directory and type:

composer dump-autoload -o

Now everything is neatly organised and you can access your classes similar to:

\MyNameSpace\Auth::staticFunction();
Moussaka answered 23/6, 2016 at 4:25 Comment(0)
F
1

Yes And NO, But what if I do generate (automaticaly) classes and methods for a very large WSDL ?

ie. for a more than hundred methods You would have probably hundred methodRequests (as a class object), next hundred methodResponse (as a Class Object) and large arrays ie ClassMap.

Sometimes it's better to handle that stuff in one file, especialy when developing without good docs for WSDL.

Fadden answered 15/2, 2018 at 13:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.