-2

I was wondering how Composer knows which classes are used in the scripts that will be executed. Does PHP provide a hooking mechanism with a callback? I'm guessing it's not inspecting the code since the following code works (provided the PHP Redis extension is installed, Redis is running on localhost with the auth token provided and the class_name key is set to the string 'App\Examples\B'):

/app/Examples/A.php
<?php namespace App\Examples;

class A
{
    public function __construct()
    {
        echo "Constructing A!\n";
    }
}
/app/Examples/B.php
<?php namespace App\Examples;

class B
{
    public function __construct()
    {
        echo "Constructing B!\n";
    }
}
/app/main.php
<?php namespace App;

use App\Examples\A;

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

$r = new \Redis;
$r->connect('localhost');
$r->auth('GJuqgx[0h-OtO94X7W[9');

// App\Examples\B
$class_name = $r->get('class_name');

$a = new A;
$b = new $class_name;

Running this from the command line produces the expected output:

$ php app/main.php
Constructing A!
Constructing B!

How does composer know to even look for App\Examples\B?

I'd like to emphasize that I am NOT asking how composer knows where to find App\Examples\B, rather, I am asking how it knows that it will need to find App\Examples\B in the first place.

kaan_a
  • 3,503
  • 1
  • 28
  • 52
  • 1
    "How does composer know to even look for App\Examples\B?" - it doesn't. The magic is in `autoload.php`, that's the file that contains the logic to look for `App/Examples/B.php` (I presume by assuming the PHP file-name matches the desired type-name). – Dai Jun 22 '20 at 11:36
  • Have a look https://getcomposer.org/doc/00-intro.md#dependency-management – Tiago Mateus Jun 22 '20 at 11:42
  • @Dai @TiagoMateus. I don't think either of you have understood the question. I've already found the answer by peeking in the composer code btw. PHP alows you to register a callback with the function `spl_autoload_register` So when PHP can not find the class it calls the registered callback(s) and checks again before throwing an exception if it still can't find it. There is also a magic function called __autoload() but it's depreciated and composer doesn't use it. – kaan_a Jun 22 '20 at 11:53
  • 1
    As soon as there is an autoloader registered, it will be used automatically. If there are more than one autoloader instances registered, the autoloading stack is processed in the order in which the autoloaders were registered. The autoloader takes a string, which is the fully qualified classname with its namespace. The autoloader is always called, when a new class is initialized with the `new` statement. – Marcel Jun 22 '20 at 12:42
  • 1
    @kaan_a But that’s exactly what I said! That `autoload.php` hooks-up with `spl_autoload_register` to do the magic you’re asking about. – Dai Jun 22 '20 at 13:19

1 Answers1

1

It 's all about the auoloading process. The PHP Introperability Group wrote a recommendation for autoloading called PSR-4. This one is used by composer.

You have to use namespaces in your PHP code. Best practice is to use a unique namespace for your composer packages. Like YourCompany\ModuleName\ and so on. These namespaces are resolved by the composer into a path containing the corresponding PHP classes. The base path is in the composer package configuration (mostly a composer.json file in your package directory). This informations are taken by the composer autoloader to find the right PHP classes.

Marcel
  • 4,854
  • 1
  • 14
  • 24
  • Sorry if I was unclear but this answers a question I did not ask. I already know what PSR4 is and understand how class names are resolved into file paths. I thought the code I included demonstrated this. What I was unclear about was the rest of the autoloading process ie how Composer knows which classes to load files for in the first place. Everybody that responded seems to have made the same mistake. Maybe I could have worded the question better, but I'm not sure how. Suggestions or edits are welcome. I already figured out the answer btw. It's in the comments of the question – kaan_a Jun 22 '20 at 12:07
  • 1
    @kaan_a Composer does not load any class or file itself, the autoloader does – Nico Haase Jun 22 '20 at 12:28
  • 1
    Sorry, if I get you wrong. Composer takes the package dependencies and the configuration of the package and creates an autoloader instance based in this settings. The order of the loaded classes is not relevant. It would be relevant, if more than one autoloader instance is used. If so, the autoloading stack is processed in the order in which the autoloaders were registered. The autoloader class created by composer just uses strings you can archive with `B::class`, which gives you the fully qualified classname. The classname used by the autoloader is always a string. – Marcel Jun 22 '20 at 12:36