Composer - Autoloading an API / Custom Installer - php

How do I autoload a set of library API functions with a composer installed library?
I have a library with a function API used to interface the libraries internal objects and want composer to automatically load the API and make it available after install without requiring the end-developer to include a file.
Currently the library is loaded by just including the __init__.php and it includes the API functions and an autoloader if required.
Thanks!

Composer always will require the end-developer to include one file, which is vendor/autoload.php. You cannot make it easier that that.
But what you can do is make including __init__.php optional because the integration of Composer allows you to use that autoloader instead. This will also work for functions, which could not really be autoloaded - Composer offers to always include a file if being told so.
So in the end your Composer configuration of that API library would look like this:
{
"name": "yourvendorname/yourfancylibraryname",
"license": "any open source identifier",
"autoload": {
"psr-0": {
"Foo_Api": "src/files"
},
"classmap": [
"extra/folders_with_any_other_class_not_conforming_to_psr0_or_psr4"
],
"files": [
"functions/file_with_your_function_definitions.php"
]
}
}
I don't know about whether your classes conform to PSR-0 or even PSR-4, but if they do, you and everyone would benefit if you can declare the autoloader with these standards. If not: Classmap will help you.
Your function definition will be loaded by the file or files mentioned in "files".
You don't need your own autoloader anymore for Composer.
Of course you could also simply mention the old __init__.php as the file to be included in "files", but this would separate your library from all the other classes, would probably be less performant (Composer already has a very good autoloader - there is no need to have two of them) and would definitely exclude all your classes from being dumped into an even faster Composer classmap autoloader.

Related

How to install html-to-markdown without composer

I want to install html-to-markdown without composer but I can't figure it out, with other libraries like Parsedown it worked just by using file location, but with html-to-markdown I don't know what I should use
This is the link for html-to-markdown
In your link there is a chapter How to use it with step by step instructions for installation.
Make sure to add require 'vendor/autoload.php'; to the top of your script, where you want to use the package.
First, use GitHub's "Code/ Download ZIP" option to get the code:
To figure out the requirements of an application meant to be installed with Composer, you need to inspect the composer.json file in the root directory:
The require key tells us the PHP extensions and third-party libraries needed:
"require": {
"php": "^7.2.5 || ^8.0",
"ext-dom": "*",
"ext-xml": "*"
},
In this case, the library is standalone, so you just need to verify your PHP installation meets the requirements. If it happened to need other packages, you'd have to repeat this for every package involved.
The autoload key tells us how the library locates and opens the files with class definitions:
"autoload": {
"psr-4": {
"League\\HTMLToMarkdown\\": "src/"
}
},
This library depends on Composer's PSR-4 autoloader implementation. We'll get back to this.
There may be other important information in the file, but in this particular case this is pretty much everything.
Regarding the autoloader... If your codebase already implements PSR-4, you just need to configure a new League\HTMLToMarkdown namespace and download the source code in the location expected by your autoloader, keeping the folder structure intact. Otherwise, I can think of a number of options, none of them particularly attractive:
Write your own autoloader.
Find a third-party PSR-4 autoloader.
Get a list of all relevant source PHP files and load them all manually:
$ find . -name '*.php'
./src/Environment.php
./src/Configuration.php
./src/Element.php
./src/ElementInterface.php
./src/PreConverterInterface.php
./src/HtmlConverterInterface.php
./src/ConfigurationAwareInterface.php
./src/Converter/TextConverter.php
./src/Converter/TableConverter.php
./src/Converter/ListItemConverter.php
./src/Converter/ListBlockConverter.php
./src/Converter/PreformattedConverter.php
./src/Converter/ConverterInterface.php
./src/Converter/DivConverter.php
./src/Converter/BlockquoteConverter.php
./src/Converter/HorizontalRuleConverter.php
./src/Converter/DefaultConverter.php
./src/Converter/CodeConverter.php
./src/Converter/ImageConverter.php
./src/Converter/HardBreakConverter.php
./src/Converter/ParagraphConverter.php
./src/Converter/EmphasisConverter.php
./src/Converter/CommentConverter.php
./src/Converter/HeaderConverter.php
./src/Converter/LinkConverter.php
./src/HtmlConverter.php
Make this into a list of require '...'; commands and play around with file order until you don't get errors.

Autoloading PHP file in composer package

I'm trying to create a composer package that also contains src/functions.php with some general functions. I have the following in composer.json to make it autoload:
"autoload": {
"files": ["src/functions.php"]
}
When I import this package into a project it will try to load src/functions.php in the current project (local) in stead of the imported package. Is there a way to ensure the correct file is loaded when imported (./vendor/bla/src/functions.php)?
Autoloading is not for loading everything. If src/functions.php contains class just ensure it's properly namespaced and I see no reason why autoloader would pick your local class instead of package's. If you are using the same namespace for the package and for code in your project then basically you should stop doing so.
If src/functions.php is just bunch of functions, then I strognly suggest refactoring the code and wrap them in properly namespaced class. You can make your functions static methods so basically not much would change from usage perspective.
EDIT
Once you finish refactoring, change your composer.json from what you shown in question to:
"autoload": {
"classmap": ["src/"]
}

How to check if composer's autoloader is being used?

I'm developing a certain PHP framework for WordPress, and I want to give my users the option to use composer to install it as a package, or to install it manually. If composer is used, then a psr-4 class autoloader handles everything. If not, then all files must be loaded manually during the framework's bootstrapping process.
Is there a safe way to check whether composer's autoloader is being used in a given WordPress environment?
Currently i'm using:
if( !class_exists('Composer\\Autoload\\ClassLoader') )
{
// Manually include files if composer is not used.
require_once 'some/files.php';
}
However, if in a given WordPress environment there is a plugin that uses composer internally, then the above if statement will return true even though other plugins have no access to it.
The solution, as it turns out, is quite simple. You need to create 2 different bootstrapping files, say manual-bootstrap.php and composer-bootstrap.php. Then add the following lines to composer.json:
"autoload": {
"files": ["composer-bootstrap.php"]
}
composer-bootstrap.php will only be called if composer is used to load the framework as a dependency. Users that want to load the framework manually will use manual-bootstrap.php instead.
if(class_exists("\Composer\Autoload\ClassLoader"))
{
// a composer autoload.php has already been included/required
}

Specifying autoloading in composer.json

I am starting to use Composer and am a bit confused on how to specify how things should be autoloaded.
My initial assumption was that one would define how to autoload classes of a package within this package. I'm however getting the impression that one should specify this in the project where the package is used. Is that the case?
I hope not! I don't want the users of a library to know how autoloading of this library works, such as for instance in which directory the classes are located. For instance, I do not want some client to know that "MyLibrary" has its classes in a directory called "includes":
"autoload": {
"classmap": [
"vendor/MyLibrary/includes/",
]
}
If on the other hand my current impression is wrong, and thus my initial assumption correct, then my question is how to achieve this. I tried using the following in the composer.json file of one of my libraries, but upon installing it somewhere, no entries would show up in the generated autoload classmap.
"autoload": {
"classmap": [
"includes/",
]
}
My initial assumption was correct. One needs to define the autoloading for a package within the composer.json file of the package. Nothing outside of the package should know about how its autoloading is done. I am unsure why what I was doing failed to work. In any case, I have not run into this recently.

Own project via composer

I've got some libraries loaded through composer, and I'm wondering if it's possible to add my own library in the /vendor map, and then to have the composer autoloader load it? The structure would be something like /vendor/mylibrary/ and then a namespace mylibrary.
Would this be possible? Also would it be possible to add a different map to the composer autoloader? Like for example /app/src/ and then to have it load all the classes in that folder? Or do I have to make my own loader for that?
Thanks
Reading the composer documentation:
You can even add your own code to the autoloader by adding an autoload field to composer.json.
{
"autoload": {
"psr-0": {"Acme": "src/"}
}
}
Composer will register a PSR-0 autoloader for the Acme namespace.
You define a mapping from namespaces to directories. The src directory would be in your project root, on the same level as vendor directory is. An example filename would be src/Acme/Foo.php containing an Acme\Foo class.
After adding the autoload field, you have to re-run install to
re-generate the vendor/autoload.php file.
So basically, you just need to follow PSR-0, and tell composer where to find your library, by adding that line to your composer.json
Yes.You can achieve it. Configure your composer.json file as following:
{
"autoload": {
"classmap": [ "classes" ]
}
Here classes is the name of the directory where you have all your application related classes.Vendor related class should be auto detected as well. Just add the following line to achieve both at the same time:
require 'vendor/autoload.php';
And you can use the namesapce to reference your class like the following:
use classes\Model\Article;
Yes, of course it is possible to add own libraries and you should feel highly encouraged to do so. If your library is available publicly, you can simply register it at packagist.org. If not, it's a bit more complicated, but not impossible.
If your project does not follow the PSR-0 standard, composer will create a classmap for you. A custom autoloader is not supported.
I'd recommend you to read the (really excellent) documentation about all this and come back, if you're running into problems.
http://getcomposer.org/doc/

Categories