I have this composer.json file
{
"require": {
"filp/whoops": "1.*"
}
}
However, I have a folder for my own project called vendor/imaqtpie/framework/src. This is not hosted anywhere, so if I do composer update to update autoload files, it gives an error.
The requested package "imaqtpie/framework" could not be found in any version, there may be a typo in package name.
I had to add this myself to autoload file to make it work.
'Framework' => array($vendorDir . '/imaqtpie/framework/src')
Is there any way to solve this?
I want to tell Composer that this local vendor folder has to be autoloaded each time regardless of checking server/version, or looking for a more elegant solution since I'm new to composer.
You have to create your own local git repository with your package code to achieve that.
After that, put something like this into your composer.json file.
"repositories": [
{
"type":"vcs",
"url":"/path/to/your/source"
}
],
"require":{
"filp/whoops":"dev-master"
}
Autoloading shouldn't be an issue if you implement it this way...
There are a few ways you can do this.
1.
I'd say the most correct way, is to host it and use Satis to produce a private 'packagist'. Then composer will behave "normally" and get the latest version, do version checking etc. but you say you don't care for this.
If you want more details I can expand on this, I have set up many satis packages and it works really well. (Note there's also the new commercial Toran Proxy which I haven't trialled yet.)
2.
If your 'imaqtpie' library is a fake vendor library (it sounds like you just have some files you've stored there, like you would an old-fashioned include library?), then you could simply use a classmap to point the autoloader to that folder from your top level application. This only makes sense if you are including that folder in your top-level app.
So your app's composer json could look like:
{
"require": {
"filp/whoops": "1.*"
},
"autoload": {
"classmap":[
"vendor/imaqtpie/framework/src"
]
}
}
So this tells composer there's a bunch of classes in that folder. When you run composer dump-autoload it will scan the folder and generate vendor/composer/autoload_classmap.php with all your files listed.
This isn't how you're supposed to use composer, but you're not asking to use composer for package management you're asking how to use composer's autoloader, which I guess is fine! as long as you understand the risks.
3.
If your package is either PSR0 or 4 (it sounds likely from the "src" folder) then you'd similarly do this in your top-level app:
{
"require": {
"filp/whoops": "1.*"
},
"autoload": {
"psr-4": {
"Imaqtpie\\Framework\\":"vendor/imaqtpie/framework/src"
}
}
}
Which again is a bit odd, but should work!
Normally, you'd specify this path in your package's composer.json and then when you do an update it gets merged into your composer.lock and then the vendor/composer/installed.json (which is the source used for the dump-autoload). But in theory you can load whatever you want from the top level app, and therefore you can 'hard code' a package into the vendor library and classpath to it.
I'd probably recommend not doing this though! The vendor folder is a tenuous location which most people and programs would assume can be destroyed and rebuilt at a whim. So it's a dangerous place to store anything which isn't in a package. It's also confusing for any other developers who will assume the same.
So I'd recommend moving your library to another location away from the vendor folder, e.g. 'lib', and then using the classpath approach above to include it in the autoloader.
Related
I have a Laravel package I would like to use in my project. I have tested it already and I know I'd need to customize quite a lot of it to fit my needs.
Overriding files in the vendor directory is always quite a chore, especially if you need to touch PHP, Vue, CSS files, etc. Hence, I don't want to go via the usual Composer installation. I also don't care much about future updates to the package, as it already has a solid base.
So the question is: After I download the package files from GitHub and after I place them in their respective directories in my Laravel app - is there a specific list of steps to take in order to make sure the inserted package works? Or is it more like, do it and fix issues one by one until it works?
Cheers.
Composer allows you to choose the local package instead of the remote one.
Create a packages folder in the base directory (the packages folder and Laravel's composer.json file must be in the same directory).
Put your downloaded package into packages (packages/packageName).
Replace the following line in your Laravel's composer.json.
"require": {
by
"repositories": [
{
"type" : "path",
"url" : "./packages/*",
"options" : {
"symLink" : true
}
}
],
"require": {
Run composer require authorName/packageName command in the console.
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.
I'm developing an app that will consist of multiple Composer packages.
First I have the "main" app (it will be a "project" in Composer) that will contain all the necessary files and folders:
app/
public/
index.php
logs/
config.php
..etc..
This is not an issue. I just set the type as "project" in the composer file so it can be install with composer create-project foo/bar.
I will also build a few optional extensions for the main app. They will be their own Composer packages. This isn't either an issue. I just make them into type "library" and install them with composer install foo/the-extension.
The issue
The extensions will have their own namespaces and some of them will have their own dependencies. A couple of them will even have the same dependencies.
This is needed since all of them will are optional. You can install one or the other or all.
Currently, I've created a new folder called "/dev" in the main app where I have all my extensions while developing. Then, in the main app, I'm loading all the extensions auto loaders:
# Main apps autoloader
require_once __DIR__ . '/vendor/autoload.php';
# Extensions
require_once __DIR__ . '/dev/foo/vendor/autoload.php';
require_once __DIR__ . '/dev/bar/vendor/autoload.php';
...etc...
This works, but it comes with a few drawbacks:
I need to change the code in the main app every time I'm going to make a commit to the main apps repo. This is a hassle and it's easy to miss something
Potential versioning clashes. If two packages depends on the same package that gets a new update. If I miss to update both, there might be a version clash. (This have happened)
It's never good to have more than one auto loader since that can mess things up royally.
So, does anyone know of a proper way of handling this, or is it one of those "well, if it works for you, do it like that"-type of situations?
Been searching for a good solution for this a while now but haven't found any. If I missed some answer here on SO, please mark it as a duplicate and I'll remove this post.
Edit
As #sammitch points out in the answer below, I could add the extensions using Composers "repositories" key. This would remove the multiple auto loader problem. However, that will make the development flow pretty awkward:
You make a change to an extension
You commit and push that change to a git repo
You do a composer update in the main app (to get the new commit)
Now you can test if your changes work
I rather not need to go through all that every single time I make a change the extensions code just to see if the change worked or not.
Whoa whoa whoa, you should only ever have one composer autoloader, and it's a bad idea to just cram in external dependencies like that as it will complicate your dev and/or deployment pipelines later.
What you want to do is have the main project include the subpackages as actual packages. You can do this either by:
1. Pushing them to a git host
https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository
{
"repositories": [{
"type": "vcs",
"url": "https://github.com/youruser/yourrepo"}],
"require": {
"youruser/yourpackage": "^1.0.0"
}
}
2. Specifying a local repo
Composer require local package
{
"repositories": [{
"type": "vcs",
"url": "/home/youruser/src/yourrepo"
}],
"require": {
"youruser/yourpackage": "^1.0.0"
}
}
Now you can simply run composer install or composer update youruser/yourpackage and composer will pull in all the necessaries and build the relevant autoloader.
Note: Repository specifications are only effective in the root composer.json, so if your dependencies have specific repo config you'll need to either put that config into the root composer.json, or into your global composer config.
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.
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/