Composer option to use alternative to composer.json? - composer-php

I've just started using the Composer feature where you tell it to look at local directories for dependencies, so that you can develop a library and something that uses that library in parallel without having to push to git to update all the time, which is awesome. e.g.
"repositories": [
{
"type": "vcs",
"url": "/documents/projects/github/guzzle"
}
],
"require":{
"guzzle/guzzle": "3.7.*#dev"
}
So when you do a composer update, Composer will pull in the version of Guzzle from the local directory, so you can test the code for a library in another application that uses that library without having to push to a repository between each code change.
However I just almost checked in the composer.json for my project with that set - which is obviously not going to work on anyone elses machine.
Is there anyway to tell composer to use a different file than composer.json, or other way to be able to tell composer to use local directories safely, without the high probability of accidentally committing a broken version of composer.json to your repository?

Use the COMPOSER environment variable:
env COMPOSER=composer-dev.json composer install
It has actually been available since at least 2012.

Instead of fetching from a local repository elsewhere you could add the option --prefer-source to the composer install/update command and remove the local repository reference.
That way composer will call git clone the software into the vendor directory, and you can develop both your software and commit to the vendor software, because that also is a fully working git repo.
Adding local repository references is not really recommended. It works when using them for real local software, but maintaining it has it's overhead: You have to mention this repository in every composer.json file that will ever load that software, even if it is only an indirect dependency (i.e. you add a software that needs THIS software as a dependency in your local repo).
Hardcoding the URL of the repository will also prevent you from changing it at will. Even though you could move the repo and change the URL accordingly, all older versions of your software still have the old URL in both composer.json and composer.lock files, and will try to load from there.

It looks like there isn't a way to do this nicely within Composer, however it is possible to hack around it.
In your composer.json file put a comment where you want to hack in some data.
{
"name": "base-reality/intahwebz",
"//": "LOCALHACK",
"require":{
"base-reality/php-to-javascript": ">=0.1.17",
"guzzle/danackguzzle": "3.3.*#dev",
...
...
}
...
}
Then have a separate file composer.local (not committed to Git) that contains the references to local directories:
"LOCALHACK",
"repositories": [
{
"type": "vcs",
"url": "/documents/projects/github/intahwebz-core"
}
],
Add a tiny PHP script called composerLocal.php to generate the new composer.json file
<?php
$srcFile = file_get_contents("composer.json");
$hackFile = file_get_contents("composer.local");
$finalString = str_replace('"LOCALHACK",', $hackFile, $srcFile);
file_put_contents("composer.json", $finalString);
?>
And a little bash script called localupdate.sh to backup the real composer.json file, generate the hacked composer.json, run Composer and then restore the original composer.json file
cp -f composer.json composer.json.bak
php composerLocal.php
composer update
cp -f composer.json.bak composer.json
Running the localupdate.sh script allows you to test the commits locally without having the danger of modifying the actual composer.json file used by the project, so there is less chance of accidentally pushing an invalid composer.json into the repository.
Just to note, Composer doesn't read the files from the respository directory, it reads the commited files in Git so you do need to commit changes made to the library code. The above process just skips the pushing step.

This should also work:
composer config --file=composer2.json && composer install
see https://getcomposer.org/doc/03-cli.md#usage

Easy, just use artifact.
In repositories add this:
{
"type": "artifact",
"url": "path/to/artifact/files/"
},
Now you just need to create the directory and zip a copy of your repository into that dir.
Name zipped files like so:
[vendorname]-[packagename]-[version].zip
example:
querypath-QueryPath-3.0.0.zip
Now you can modify the package locally and it will pull from the zip file instead of the online repo.
In require add it like so and specify version as defined in zip:
"querypath/QueryPath": "3.0.0",
With this method you will have the ability to edit the vendor files and composer will still update any autoloaders relative to the changes and it will leave your changes alone.

Related

Why does npm install use a different package version than our forked one?

Since a few days, our aws elastic beanstalk fails to deploy our code through npm Install.
We are using our own fork from parse-server repo, and it always worked fine.
Unfortunately it now fails without obvious reason. When looking at the instance logs it clearly shows it tries to use the original parse-server repo (on a very old branch) instead of our very own fork, but I can't figure why.
Our package.json file indicates:
"parse-server": "git+https://github.com/hulab/parse-server.git#patched/5.3.0-hulab-2"
and our npm-shrinkwrap.json file reflects it with a
"parse-server": {
"version": "git+https://github.com/hulab/parse-server.git#54bfd65181f19d4296f0ebea79cf3a4ab542f2fc",
"from": "git+https://github.com/hulab/parse-server.git#patched/5.3.0-hulab-2",
...
}
Whereas the EC2 instance logs indicate failures when installing:
parse-server#github:parse-community/parse-server#892c6f94d50b6dced8a5e1948e058dc7b095c914
I can't figure out why this branch is used while not being referred to in any of our files!
Any help would be very appreciated :)
It is likely another dependency that points to that specific version of Parse Server.
For example, the Parse JS SDK has a devDependency for integration tests:
"parse-server": "github:parse-community/parse-server#alpha"
Since you are using a customized version of Parse Server, check the Parse JS SDK (which is a component of Parse Server), and any other Parse dependency that you added, whether they have a parse-server dependency and to where it points. In package.json you may only see the branch name but in package-lock.json of that dependency you may see the actual commit hash you are referring to.

How to use git in vendor folder of fork?

I always use composer packages in Laravel but I never changed one. This is my first time and I don't want to do it incorrect.
I need to use and change a packages foo/bar. Everything that follows now is just guessed:
I forked the repo
I created a develop branch
I added a vcs to my composer.json
"require": {
//...
"foo/bar": "dev-develop",
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/thisisme/bar"
}
],
composer update
Now I have the thisisme/bar fork in my vendor folder in foo.
So far so good. Now I can use my own fork.
But currently, as I don't know what is good practice to modify the repo, I cloned the repo to a completely different location. Then I push my changes there and run composer update in my project to get the changes. But this is a pain.
Do I need to have a sub git in my project in vendor/foo with
git remote add origin https://github.com/thisisme/bar.git. Because "git in git" feels wrong and finally is not really working as git commands seem to interact with the "parent git".
While VonCs answer is correct regarding git, I'm not certainly sure that git submodule support is well aligned with composer(1) vendor dir for packages from a VCS repository. At least I have not experimented much with it and when I use a composer configuration with a VCS git repository, I normally don't need that1.
While composer(1) has support for git for vendor packages, it is on repository level, that is, you can have your own repository for your package (as you have configured it shown in your question) and then composer takes care of updating (or giving a warnings about local changes).
composer(1) supports this with its own remote for the packages (non-bare) clone (in the source install, read on).
So yes, what you describe ("But this is a pain."), is as long as you don't use it to your benefit. While you develop your (cloned) package, you don't need to run composer update all the time.
.git
composer.json
vendor/foo/bar/.git
A Composer project with two Git repositories
This is why IMHO "git in git" must not feel wrong. Similar to git sub-modules, git supports this very well. By default it even keeps track in the parent project of the current revision (changes) of the sub-project but without having the information of the remote - as it is local (gitlink).
You won't see this thought as within the tree, the gitlink would be at vendor/foo/bar and commonly (& given that) vendor is git ignored, no version tracking in the main project for vendor/foo/bar/.git - but there in the sub-project.
This is not a problem as Composer manages that git sub-project for you (the initial clone and further checkouts) in terms of your main project.
And git realizes it is a different project.
You should be able to cd into the package directory within the vendor folder (vendor/foo/bar) and configure your remote(s) there. You can then work within that project and git(1) will work there and not within the parent repository.
To have this work with composer(1) it is important that you configure composer to prefer the source install variant for that repository. This is the preferred-install option and you can configure it for your repository specifically.
{
"config": {
"preferred-install": {
"foo/bar": "source"
}
}
}
From the wording in your question, I assume that you have not yet configured it.
And this is somewhat important as only with the source install, there will be a (non-bare) git clone in vendor/foo/bar and therefore the git checkout with the overall git configuration within the packages folder in the vendor directory (as you have Github configured as the repository source and composer optimizes to take the dist version by default IIRC).
After you changed your configuration to the source install and updated it, cd into vendor/foo/bar and then run git remote -v. It now should show you the "composer" remote(s) for that package.
As you use the develop branch, you can add changes locally but mind the gap that you would also need to push them to the remote repository (Github) before you use composer again to update (at least) that foo/bar package - as while you use git for the development of the foo/bar package now, in your main project you use composer to manage the dependency.
This is the price you have on the payroll using Github instead of a configuration that is more near to the place of work, but at least locally, you can handle the package with "git in git".
This is normally straight forward. One overall price remains thought, due to managing two instead of one repository but that you can't prevent with this kind of composer project [composer only versioned vendor folder]).
Note: If development takes longer than a few hours, it may also make sense to include the new Git sub-project in the backup routine of your parenting project, so that when you remove the folder vendor/foo/bar you have a backup of the (local) Git repository and working tree in it. However, this depends on the project configuration and is your own responsibility.
A bit of a workflow with some hints is also outlined in the composer documentation in Loading a package from a VCS repository.
1 There is a type of setup for a composer project where vendor itself is under git version control, with that git sub-modules can work (very well), but this is most likely not the kind of setup you have for your project, so I skip it for this answer.
If you're working with sail or docker-compose and linking the foo/bar project in the vendor dir is only a temporary until 'it works' solution you could just add it as a volume link. This is what I usually do.
Eg: I'm working on my-project in ~/projects/my-project, I clone the foo/bar repo to ~/projects/bar
Then in the docker-compose.yml I can add the volume:
volumes:
- .:/var/www/html
- ../bar:/var/www/html/vendor/foo/bar
Again, this has a huge assumption on docker being used, but I like to think that everybody is using it these days.
Do I need to have a sub git in my project in vendor/foo with git remote add origin https://github.com/thisisme/bar.git.
That could be achieved with a submodule which allows for your parent Git repository to only store a reference to another repository.
You would use git submodule add for that.
A git clone --recurse-submodule would therefore clone your project with the submodule Git repository in it cloned as well, and checked out to the exact reference you previously committed.

Composer from local repos InvalidArgumentException

I am trying to create a module based on this example Oxid 6 module
https://github.com/linslin/oxid6-example-module
I have changed and cloned it to
https://github.com/v3ritas1989/gg_oxid6-example-module
as well as into my local module folder
..modules/compname/modulename
So for the beginning I want to change the modulename, submodul folder name and the namespace given
modules/companyname/modulename
Path Example:
modules/linslin/oxid6-example-module
However if I try to install my module
via composer
composer require compname/gg_oxid6-example-module:dev-master
(for local folder)
composer require v3ritas1989/gg_oxid6-example-module:dev-master
(for git)
I get ERROR:
[InvalidArgumentException] Could not find a matching version of
package compname/gg_oxid6-example-module. Check the package
spelling, your version constraint and that the package is available in
a stability which match es your minimum-stability (stable).
What I dont understand is why
composer require linslin/oxid6-example-module:dev-master
is working even so I deleted the local folder linslin
I guess it is pulling it from github?
but why then does this not work with my changed module and my github repo?
I made only search replace
modulename
compname
namespacename
Question:
I am assuming composer just does not find my repo or local.. so
How do I do composer require in a way that it only checks my local
folder?
Why does it also not find it in my github?
you need to register repository in your main composer.json file as described here:
https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository
or register your package in https://packagist.org/ so it would be automatically detected.
There are also other ways of registering repositories, for example define it as local repository: https://getcomposer.org/doc/05-repositories.md#path

node_module errors with AWS lambda, what's the best practice for dependencies?

I've been trying to convert and deploy one of our node.js apps into a lambda function and have been having some problems with the node_modules dependencies - saying that it can't find certain modules. I started by creating a package.json, npm install the dependencies locally then copy the node modules folder up to lambda.
For instance I have a project that requires sequelize and convict and have been getting errors saying that it cannot find the moment module as a sub-dependency. I see that moment is included in the root of my node_modules but it was not included in the sub folder under the sequelize module.
However, this project runs fine locally. What is the difference in lambda and what's the best practice for deploying a somewhat long list of node modules with it - just a copy of the node_modules folder? On some of the other simpler projects I have, the small amount of node_modules can be copied up with no problems.
{
"errorMessage": "Cannot find module 'moment'",
"errorType": "Error",
"stackTrace": [
"Function.Module._resolveFilename (module.js:338:15)",
"Function.Module._load (module.js:280:25)",
"Module.require (module.js:364:17)",
"require (module.js:380:17)",
"VERSION (/var/task/node_modules/sequelize/node_modules/moment-timezone/moment-timezone.js:14:28)",
"Object. (/var/task/node_modules/sequelize/node_modules/moment-timezone/moment-timezone.js:18:2)",
"Module._compile (module.js:456:26)",
"Object.Module._extensions..js (module.js:474:10)",
"Module.load (module.js:356:32)",
"Function.Module._load (module.js:312:12)"
]
}
I resolved this by uploading all from a zip file which contains all the data I need for my lambda function.
you can just create your project in your local machine and make all the changes that you need then the file you are going to zip should have this same structure and also see that there is an option to load your code from a zip file.
This sounds to me like an issue caused by different versions of npm. Are you running the same version of nodejs locally as is used by Lambda (ie. v0.10.36)?
Depending on the version of npm you're using to install the modules locally, the node_modules directory's contents are laid out slightly differently (mainly in order to de-duplicate things), and that may be why your dependencies can't find their dependencies in Lambda.
After a bit of digging, it sounds like a clean install (ie. rm your node_modules directory and run npm install) might clean things up for you. The reason why is that it seems that npm doesn't install sub-dependencies if they're already present at the top level (ie. you installed moment before sequelize, etc).

multiple projects with same vendor folder on Laravel 4

I have multiple projects with very little space to keep.
since most of them uses nearly same packages (only 1 uses phpexcel and the other one swiftmailer ) and vendor folder required biggest space on laravel.
I thought maybe I could use same vendor folder for every of them.
I actually messed with autoload.php and some other config files however I couldn't make it.
simply I'll put vendor folder under public_html and create folder like project1 project2.
under those folders I'll put everything about my projects except vendor folder and then make them subdomain.
Short answer:
You can't.
Long answer:
/vendor folder is not just about packages, you also have in there vendor/composer folder, where your application classes names are stored for autoloading purposes. Everytime you run composer dump-autoload, Composer changes the content of some files there. Take a look at the vendor/composer/autoload_classmap.php file, you'll see that some of those classes are from your own project.
Workaroud:
Please note that I don't see a thing like this going well, but you can, actually, create a blank project, just for package downloading and symlink all packages from all your vendors folders to that one. It's a lot of trouble for a little gain. But it's up to you, of course.
Source: http://www.wenda.io/questions/2416709/laravel-4-1-vendor-directory-config.html
edit composer.json
"config": {
"preferred-install": "dist",
"vendor-dir": "../vendor"
},
edit bootstrap/autoload.php file
require __DIR__.'/../../vendor/autoload.php'
edit bootstrap/start.php file
$framework = $app['path.base'].
'/../vendor/laravel/framework/src';
edit ../vendor/laravel/framework/src/Illuminate/Foundation/Console/Optimize/config.php
$basePath = $app['path.base'].'/../';
then run composer install, you will find vendor dir created ../
php artisan optimize -v --force
Generating optimized class loader
Compiling common classes

Resources