# RFC: spl_autoload_register() should provide kind of entity to load

- Thread: https://externals.io/message/85860
- Original archive: https://news-web.php.net/php.internals/85860
- Started by georges on 2015-04-18T14:24:34+00:00
- Messages: 8
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #85860 — georges — 2015-04-18T14:24:34+00:00

URL: https://externals.io/message/85860#85860

​Hi php internals,

Currently `spl_autoload_register()` pass the name of the class entity to the
first *Callable* argument​, but there is now way (as i far i know) to know
what kind of entity we're looking for.
-Class ?
-Interface ?
-Trait?


A second argument should be added to the *Callable* function describing
what kind of entity we're looking for.

Example:

<?php

// function __autoload($class) {
//     include 'classes/' . $class . '.class.php';
// }

function my_autoloader($entity, $kind = "class") {
   // Kind would be: class/interface/trait
   include $kind . '/' . $entity . ".{$kind}.php";
}

spl_autoload_register('my_autoloader');

// Or, using an anonymous function as of PHP 5.3.0
spl_autoload_register(function ($entity, $kind = "class") {
   // Kind would be: class/interface/trait
   include $kind . '/' . $entity . ".{$kind}.php";
});

?>


In fact i think currently that Autoload is too much "class oriented" as per
reading php docs, whereas that php currently allow the autoload of many
entities. It can really confuse probies php developers :(

*Pros*:

   - -Avoid multiple else if() for testing an existing file to load the
   entity.
   - -As we now know the type of entity to load, it help reduce I/O
   activity, then reduce  timespend.
   - -Clarify the code: We now  what the autoloader will load
   - -Keep the BC safe


*Cons*:

   - -None



Regards,
Georges.L

---

## #85861 — Anthony Ferrara — 2015-04-18T15:08:00+00:00

URL: https://externals.io/message/85860#85861 · In reply to: #85860

Georges,


> Hi php internals,
>
> Currently `spl_autoload_register()` pass the name of the class entity to the
> first *Callable* argument, but there is now way (as i far i know) to know
> what kind of entity we're looking for.
> -Class ?
> -Interface ?
> -Trait?
>
>
> A second argument should be added to the *Callable* function describing
> what kind of entity we're looking for.
>
> Example:
>
> <?php
>
> // function __autoload($class) {
> //     include 'classes/' . $class . '.class.php';
> // }
>
> function my_autoloader($entity, $kind = "class") {
>    // Kind would be: class/interface/trait
>    include $kind . '/' . $entity . ".{$kind}.php";
> }
>
> spl_autoload_register('my_autoloader');
>
> // Or, using an anonymous function as of PHP 5.3.0
> spl_autoload_register(function ($entity, $kind = "class") {
>    // Kind would be: class/interface/trait
>    include $kind . '/' . $entity . ".{$kind}.php";
> });
>
> ?>
>
>
> In fact i think currently that Autoload is too much "class oriented" as per
> reading php docs, whereas that php currently allow the autoload of many
> entities. It can really confuse probies php developers :(
>
> *Pros*:
>
>    - -Avoid multiple else if() for testing an existing file to load the
>    entity.
>    - -As we now know the type of entity to load, it help reduce I/O
>    activity, then reduce  timespend.
>    - -Clarify the code: We now  what the autoloader will load
>    - -Keep the BC safe
>
>
> *Cons*:
>
>    - -None
>

This won't work out of the box due to `spl_autoload()`. If you use that
default autoloader (by calling `spl_autoload_register()`), it will
accept an optional second argument as the list of file extensions.
Which means that having `spl_autoload_register()` pass a second argument
to autoloaders will break the existing core autoloader. Changing the
core autoloader is also not really possible due to BC considerations.

So technically, without introducing a new autoload API, this won't
really be possible.

As far as the feature, I would question why you need to distinguish
the file by the type. The names are in the same symbol table, so you
couldn't possibly have a collision. From there, is the identification
of the type of the definition in the filename that important? Isn't
that just another form of Hungarian Notation?

Anthony

---

## #85862 — Ryan Pallas — 2015-04-18T15:09:36+00:00

URL: https://externals.io/message/85860#85862 · In reply to: #85860

> ​Hi php internals,
>
> Currently `spl_autoload_register()` pass the name of the class entity to the
> first *Callable* argument​, but there is now way (as i far i know) to know
> what kind of entity we're looking for.
> -Class ?
> -Interface ?
> -Trait?
>
>
> A second argument should be added to the *Callable* function describing
> what kind of entity we're looking for.
>
> Example:
>
> <?php
>
> // function __autoload($class) {
> //     include 'classes/' . $class . '.class.php';
> // }
>
> function my_autoloader($entity, $kind = "class") {
>    // Kind would be: class/interface/trait
>    include $kind . '/' . $entity . ".{$kind}.php";
> }
>
> spl_autoload_register('my_autoloader');
>
> // Or, using an anonymous function as of PHP 5.3.0
> spl_autoload_register(function ($entity, $kind = "class") {
>    // Kind would be: class/interface/trait
>    include $kind . '/' . $entity . ".{$kind}.php";
> });
>
> ?>
>
>
> In fact i think currently that Autoload is too much "class oriented" as per
> reading php docs, whereas that php currently allow the autoload of many
> entities. It can really confuse probies php developers :(
>
> *Pros*:
>
>    - -Avoid multiple else if() for testing an existing file to load the
>    entity.
>    - -As we now know the type of entity to load, it help reduce I/O
>    activity, then reduce  timespend.
>    - -Clarify the code: We now  what the autoloader will load
>    - -Keep the BC safe
>
>
> *Cons*:
>
>    - -None
>
>
>
> Regards,
> Georges.L
>

I'm not sure I agree. Even in your example, the $kind is in the path twice,
which seems redundant. With a good naming system, the namespace and/or
object name will tell you what it is. IE:

Library\Module\DataInterface maps to
/path/to/project/library/module/DataInterface.php
Library\Module\LogInterface maps to
/path/to/project/library/module/LogInterface.php

Library\Traits\Singleton maps to
/path/to/project/library/traits/Singleton.php

Also, check out PSR-0 and PSR-4 (not affiliated with the PHP devs, but
framework owners developing for PHP) which shows how naming conventions
like this can lead to only a single file exists check, further simplifying
the autoloader.

Maybe its not the best code, but this is how simple my autoloader is with a
naming convention like this (Note: DS = `DIRECTORY_SEPARATOR` but its too
long):

spl_autoload_register(function ($strClass)
{
    $strFile = $strClass . '.php';
    $strNameSpace = '';
    if ( ($iLast = strripos($strClass, '\\')) !== false ) {
        $strNameSpace = DS . str_replace('\\', DS, substr($strClass, 0,
$iLast));
        $strNameSpace = implode('_',
preg_split('/(?<=[a-zA-Z])(?=[A-Z])/s', $strNameSpace));
        $strFile = substr($strClass, $iLast + 1) . '.php';
    }
    $strFilePath = ROOT . strtolower($strNameSpace) . DS . $strFile;
    if( is_readable($strFilePath) ) {
        require_once $strFilePath;
        return true;
    }
    return false;
});

As you can see, by the result of the naming convention, I know where the
class/interface/trait will be defined based on its namespace and name.
Since traits live under a traits folder, its obvious from their location on
the filesystem what they are (no need to .trait.php at the end).
Additionally since Interface is how all interfaces end in name, the
filename would be redundant to have .interface.php at the end.

-Ryan

---

## #85863 — georges — 2015-04-18T15:20:28+00:00

URL: https://externals.io/message/85860#85863 · In reply to: #85862

Effectively from this perspective, i get it. I'm not a fan of PSR-4
convention as they are not officialy supported by PHP but i understand your
both (Ryan, Anthony) point of view.

Also well done for catching the Hungarian notation, i just noticed that is
a bad pratice.

Anyway, thanks for your (quick) feedback.

Regards.

Geolim4

2015-04-18 17:09 GMT+02:00 Ryan Pallas <derokorian@gmail.com>:

>
>
> 
>
> > […]
>
> I'm not sure I agree. Even in your example, the $kind is in the path
> twice, which seems redundant. With a good naming system, the namespace
> and/or object name will tell you what it is. IE:
>
> Library\Module\DataInterface maps to
> /path/to/project/library/module/DataInterface.php
> Library\Module\LogInterface maps to
> /path/to/project/library/module/LogInterface.php
>
> Library\Traits\Singleton maps to
> /path/to/project/library/traits/Singleton.php
>
> Also, check out PSR-0 and PSR-4 (not affiliated with the PHP devs, but
> framework owners developing for PHP) which shows how naming conventions
> like this can lead to only a single file exists check, further simplifying
> the autoloader.
>
> Maybe its not the best code, but this is how simple my autoloader is with
> a naming convention like this (Note: DS = `DIRECTORY_SEPARATOR` but its too
> long):
>
> spl_autoload_register(function ($strClass)
> {
>     $strFile = $strClass . '.php';
>     $strNameSpace = '';
>     if ( ($iLast = strripos($strClass, '\\')) !== false ) {
>         $strNameSpace = DS . str_replace('\\', DS, substr($strClass, 0,
> $iLast));
>         $strNameSpace = implode('_',
> preg_split('/(?<=[a-zA-Z])(?=[A-Z])/s', $strNameSpace));
>         $strFile = substr($strClass, $iLast + 1) . '.php';
>     }
>     $strFilePath = ROOT . strtolower($strNameSpace) . DS . $strFile;
>     if( is_readable($strFilePath) ) {
>         require_once $strFilePath;
>         return true;
>     }
>     return false;
> });
>
> As you can see, by the result of the naming convention, I know where the
> class/interface/trait will be defined based on its namespace and name.
> Since traits live under a traits folder, its obvious from their location on
> the filesystem what they are (no need to .trait.php at the end).
> Additionally since Interface is how all interfaces end in name, the
> filename would be redundant to have .interface.php at the end.
>
> -Ryan

---

## #85864 — Nikita Popov — 2015-04-18T15:26:10+00:00

URL: https://externals.io/message/85860#85864 · In reply to: #85860

> ​Hi php internals,
>
> Currently `spl_autoload_register()` pass the name of the class entity to the
> first *Callable* argument​, but there is now way (as i far i know) to know
> what kind of entity we're looking for.
> -Class ?
> -Interface ?
> -Trait?
>
>
> A second argument should be added to the *Callable* function describing
> what kind of entity we're looking for.
>

This is not possible, because we do not generally know if something is a
class or an interface or a trait when autoloading it. E.g. if I write
class_alias('X', 'Y') and X is autoloaded, it could be a class an interface
or a trait - it just doesn't matter.

Nikita

---

## #85865 — Stanislav Malyshev — 2015-04-18T21:15:36+00:00

URL: https://externals.io/message/85860#85865 · In reply to: #85860

Hi!

> Currently `spl_autoload_register()` pass the name of the class entity to the
> first *Callable* argument​, but there is now way (as i far i know) to know
> what kind of entity we're looking for.
> -Class ?
> -Interface ?
> -Trait?

I'm not sure it would be very useful for the engine. It is obviously
useful for your particular naming scheme, but most people do not use
this scheme, so this is not very common use case. I'd even argue it
usually not the best practice, as class and interface names may be used
interchangeably in typed parameters, return types, instanceof checks,
etc. and one could convert class to interface easily without breaking
anything (except your naming scheme).

Also, while in the many common cases it is known which entity is
required, there's no guarantee it is known in all cases and I'm pretty
sure there could be cases where it's not known - in fact,
zend_lookup_class() API has only the name as its input.

-- 
Stas Malyshev
smalyshev@gmail.com

---

## #85868 — francois@php.net — 2015-04-19T13:33:30+00:00

URL: https://externals.io/message/85860#85868 · In reply to: #85860

> De : georges [mailto:geolim4@gmail.com]
>
> Currently `spl_autoload_register()` pass the name of the class entity to the
> first *Callable* argument​, but there is now way (as i far i know) to know
> what kind of entity we're looking for.
> -Class ?
> -Interface ?
> -Trait?

As others already said, classes, interfaces, and trait names share the same table, and there are a lot of places where you cannot determine the type you're looking for when autoloading a symbol.

However, we'll need to provide a type when we extend autoloading to functions and constants, if we do it someday.

Regards

François

---

## #85869 — georges — 2015-04-19T13:36:04+00:00

URL: https://externals.io/message/85860#85869 · In reply to: #85868

Yes, i finally rewritten major part of my code following the recommended
SF2 standard for naming convention of trait/interfaces.

Thanks Internals.

Regards,
Geo.

Geolim4

2015-04-19 15:33 GMT+02:00 François Laupretre <francois@php.net>:

> > […]
> the
> > […]
> know
> > […]
>
> As others already said, classes, interfaces, and trait names share the
> same table, and there are a lot of places where you cannot determine the
> type you're looking for when autoloading a symbol.
>
> However, we'll need to provide a type when we extend autoloading to
> functions and constants, if we do it someday.
>
> Regards
>
> François
