Search code examples
phpnamespacesphpspreadsheet

How to use "USE" with PHPSpreadsheet


I am getting more and more confused as I read through various SO posts and the PHP Manual on how to properly set up the "USE" for PHPSpreadsheet. I installed the files manually (not through Composer) and all the posts/references I've read seem to imply that I should set it up this way:

use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

My folder structure does not follow this format and is set up this way (for example):

/phpscripts/phpspreadsheet/IOFactory.php

I'm now wondering if the folder structure is not related to how the "USE" is configured/utilized but I have not found any posts that explain this for my level of understanding. I see a few references to the use of "REQUIRE" that points to the exact location of the specific files but that is just adding to my confusion. Could someone elaborate on how this should be properly set up?


Solution

  • The thing that composer does for you is to provide what is called an autoloader, which basicly loads the files which contain the classes that your code needs at runtime.

    Registering a autoloader is done through the function spl_autoload_register where you provide it a callable that should be run when your code requests a class that is not known to PHP.

    So when using a composer package without composer you would need to make your own autoloader for that specific library.

    As you noticed the FQCN(fully qualified class name) aka. (namespace + class name) does not always correspond to the location of the file containing that class. The namespace of a class is actually defined in the file containing the class(typically in the top of the file).

    PSR-4 is a standard that:

    describes a specification for autoloading classes from file paths.

    and if you look in the PhpSpreadsheet composer.json you can see that they follow that standard so that makes it easier to implement our own autoload now that you have decided not to use composer.

    here is my attempt at loading the PhpSpreadsheet without composer

    use PhpOffice\PhpSpreadsheet\IOFactory;
    
    spl_autoload_register(function ($class) {
        $path = 'phpscripts/phpspreadsheet'; // Replace this with the path to where PhpSpreadsheet is stored.
        
        //Split the FQCN into parts
        $fqcnParts = explode('\\', trim($class, " \t\n\r\0\x0B\\"));
        
        //check that we have atleast 3 parts and that the vendor namespaces matches our package
        if (count($fqcnParts) < 3 || $fqcnParts[0] != 'PhpOffice' || $fqcnParts[1] != 'PhpSpreadsheet') {
            return;
        }
        // read the comments in this next parts from the inside -> out
        $filePath = 
            rtrim($path, '/') . '/' . // prefix with our path to the library
            ltrim(
                implode( // implode the remaining parts into a string split by /
                    '/', 
                    array_slice($fqcnParts, 2) // Remove the vendor namespaces
                ), 
                '/'
            ) . '.php'; // suffix the file extension
        if (file_exists($filePath)) {
            include $filePath;
        }
    });
    
    var_dump(class_exists(IOFactory::class)); // this line will try to autoload the IOFactory class
    

    Hope this helps you otherwise feel free to hit me up :-)