Composer package in a vcs subfolder - how to reference? - php

I have created a GIT repo with some URL. Inside that repo is a folder Release and that contains a composer package - composer.json file, PHP files, etc.
Now, how do I reference this package in another project? Attempt one:
{
"require" : {
"my/package/Release": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:my/package.git"
}
]
}
Result:
No valid composer.json was found in any branch or tag of git#bitbucket.org:my/package.git, could not load a package from it.
Attempt two:
{
"require" : {
"my/package": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:my/package.git/Release"
}
]
}
Result:
[RuntimeException]
Failed to execute git clone --mirror 'git#bitbucket.org:my/package.git/Result' '/home/user/.cache/composer/vcs/git-bitbucket.org-my-package.git-Result/'
Cloning into bare repository '/home/user/.cache/composer/vcs/git-bitbucket.org-my-package.git-Result'...
repository does not exist.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Composer documentation doesn't help either. Is this possible at all?

Related

PHP composer: Update local path repository dependency

I have a project which requires a bunch of local path repositories. Those local path repositories partly require each other and also remote repositories.
For example one of the local repo composer.json looks like this:
{
"description": "",
"type": "neos-project",
"name": "mapo/campaign",
"repositories": [
{
"type": "path",
"url": "Source/Mapo.NodeTypes"
}
],
"require": {
"mapo/nodetypes": "*"
},
"autoload": {
"psr-4": {
"Mapo\\Campaign\\": "Classes/"
}
},
"extra": {
"neos": {
"package-key": "Mapo.Campaign"
}
}
}
The mapo/nodetypes local package then requires also a private remote repository:
{
"description": "",
"type": "neos-project",
"name": "mapo/nodetypes",
"minimum-stability": "dev",
"repositories": [
{
"type": "git",
"url": "url to private repo.git"
},
{
"type": "path",
"url": "../Mapo.Somepackage"
},
],
"require": {
"mapo/privateproject": "*",
"mapo/somepackage": "#dev"
},
"autoload": {
"psr-4": {
"Mapo\\NodeTypes\\": "Classes/"
}
},
"extra": {
"neos": {
"package-key": "Mapo.NodeTypes"
}
}
}
Now I need to test a new feature in mapo/privateproject. So I created a new branch in the private repo called issue0815 and made my changes. I also created a new branch issue0815 in the main mapo project (which has the local path composer.json changes locally).
I updated the dependency of mapo/nodetypes to "mapo/privateproject": "dev-issue0815",.
My problem is that, no matter which command, composer refuses to install the issue0815 branch for the private repository. At first composer complained, that it cannot install the dependency dev-issue0815 because the composer.lock prevented it. So I removed all usages of the private repo and the mapo/nodetypes from my composer.lock.
What surprised me the most, was that composer recovered the original composer.lock file. It just completely ignored my current local main project branch - which has the modification for the local path repo composer.json files and just required the contents from the master branches.
So, how can I update a dependency of a local path repo which needs a specific branch from a private repo?
This one took me quite a while, but the reason why my changes to composer.json have been completely ignored including also when I deleted the composer.lock was that, composer ignores your changes if it concludes, that the packages from vendor/composer/installed.json are correct.
From https://github.com/composer/composer/issues/4312#issuecomment-191488570:
Right now Composer prefers installed packages, derived from the installed.json file. So as long as the replacement is valid, it will indeed keep generating the same solution and thus lock. This is just because that's how Composer works internally.
To 'reset' it completely and make it rethink its installed packages (before it automatically 'corrects' because of package updates) you'd have to remove vendor/composer/installed.json as well as the lock. This will trigger a complete reevaluation of dependencies and reinstall. You could also just go for the full cleanup then and delete the entire vendor directory.
Thats also the reason why it is often suggested to remove the vendor directory, I think.

Private repo composer.json not being used

My problem is that a privately made repo's composer.json seems to be broken when trying to use it as a package elsewhere.
I have a private repo with code needed for other projects. The repo's composer.json looks like this:
{
"name": "somevendor/global",
"require": {
"nesbot/carbon": "^1.21"
},
"autoload": {
"psr-4": {
"" : "src/"
},
"files": [
"somedir/somefile.php"
]
}
}
The src is in the base directory of the repo, and contains PSR-4 namespaced classes. I have namespace folders within that, e.g. a Foo directory with classes in the Foo namespace:
-- src
-- Foo
// some Foo\... classes
// some global namespace classes
-- somedir
somefile.php // A file with helper functions
In the project folder, I'm accessing the somevendor/global repo via a composer.json file:
{
"require": {
"somevendor/global-folder": "dev-master"
},
"repositories": [
{
"type": "package",
"package": {
"name": "somevendor/global",
"version": "dev-master",
"type": "package",
"source": {
"url": "git#bitbucket.org/somevendor/global.git",
"type": "git",
"reference": "master"
}
}
}
]
}
Running composer install in the project folder seems to work at first. I have installed SSH keys properly so it can access the private repo on Bitbucket and grab the files:
$ composer install
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing somevendor/global (dev-master master)
Cloning master
Writing lock file
Generating autoload files
And then in the project's PHP code I require vendor/autoload.php, but none of the classes are being autoloaded, including the Carbon package specified in the first repo's composer.json file:
Fatal error: Uncaught Error: Class 'Foo\Foo' not found in...
I've clearly made a mistake here, have I structured the first repo wrongly?
I "solved" this by taking out all of the "require" entries from the remote repo's composer.json file and moving them to the local website's composer.json file.
This is what the files looked like:
The remote private repo's composer.json:
{
"name": "somevendor/global",
"license": "proprietary",
"autoload": {
"psr-4": {
"" : "src/"
},
"files": [
"functions/functions.php"
]
}
}
The local website's composer.json:
{
"require": {
"nesbot/carbon": "^1.21",
"somevendor/global": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:somevendor/global.git"
}
]
}
It kept throwing Composer\Repository\InvalidRepositoryException because I forgot to put the name into the remote repo's composer.json file, so don't forget that bit!
Also remember to set up your git ssh keys if you've set them up. I used this Bitbucket tutorial to do this.

Composer, Laravel and local packages

My issue is I have a package which isn't a repository and I am trying to get it to play nice with Laravel and composer. It is still located under the vendor folder, the only issue is that if I simply set:
"psr-0": {
"Test\\Test": "vendor/test/test/src/"
}
This will load the service provider but none of the controllers etc will autoload. What is the correct way to implement a package with larval that does not have it's own repository. Or does this go against the nature of packages and this should simply be structured under the applications controllers.
The package was created by me using workbench but I found i did not really need this as a separate repository but it would still be good to keep it as a package. Therefore the structure is exactly the same as a regular package:
vendor
testvendor
testpackage
public
src
tests
.gitignore
composer.json
phpunit.xml
UPDATE:
As a solution for the time being I am using:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php",
"vendor/package"
]
},
As an entry in the class map. Looking forward I will probably refactor this into the app folder or create a repository for this package.
If you have some classes that you're calling "package", you're not supposed to add those files to your vendor folder. This folder is managed by composer and at any time you might loose it. Create a subfolder in your application and put those files there.
You have to be sure your PSR-0 autoloading will work for every single file in your folder structure. So, if your root is vendor/test/test/src/ and your namespace is
Test\\Test
All your files must be in
vendor/test/test/src/Test/Test/ClassFileName.php
PSR-4 is easier to deal and understand, this
"psr-4": {
"Test\\Test\\": "vendor/test/test/src/"
}
Means that your files would have to be like:
vendor/test/test/src/ClassFileName.php
Doublecheck your namespaces. It's easy to make mistakes when using namespaces with PSR-0 and remember that
composer dump-autoload
Must be ran every time you change things in composer.json or create new files. If it's a simple class autoloading, every time you create a file, if it's a PSR-X autoloading, everytime you create or update a namespace in your composer.json file.
If what you have is is really a package you should use Composer: when your package is structured as a composer package (check Laravel's composer.json as an example), the correct way of adding it to your application, if it's not list in Packagist, is via repositories.
You can have (non-packagist) packages in a public VCS repository:
{
"require": {
"monolog/monolog": "dev-bugfix"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/igorw/monolog"
}
]
}
You can have (non-packagist) packages in a protected by password VCS repository (git, bitbucket...):
{
"require": {
"vendor/my-private-repo": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:vendor/my-private-repo.git"
}
]
}
You can have your packages zipped in your hard drive and load them via the artifact repository type:
"repositories": [
{
"type": "artifact",
"url": "path/to/directory/with/zips/"
}
],
Though #Antonio Carlos Ribeiro's answer is really nice, I had problem with installing custom packages locally(which is also stated in the last part of his answer)
Let's assume this is the directory structure of the package we are trying to install:
D:/test_pack
src/
composer.json
If you do not want to upload your custom package (that most likely you have developed, yourself) to online repositories you can use one of the following two methods:
Method I
(You have to specify version for your package, otherwise you'll get this error: The requested package could not be found in any version, there may be a typo in the package name.)
1) In composer.json, Add version to your package. your package's json should look something like this:
{
"name": "gandalf/test_pack",//This is your package's name
"description": "some desc",
"version": "1.0.0",//This is the version that you have to specify
"authors": [
{
"name": "gandalf the grey",
"email": "fake#yahoo.com"
}
],
"minimum-stability": "dev",
"require": {
"laravel/framework": "~5.4"
},
"autoload": {
"psr-4": {
"Gandalf\\BotPack\\": "src/"
}
} }
2) zip your package(let's assume the zip file is in D:/test_pack/test_packa.zip)
3) In laravel's composer.json add your package name (in our case gandalf/test_pack into require part of json) and add the repository array to the composer.json file and in that array specify the directory in which your package's zip file exists(in our case D:/test_pack) . like this
{
...,
"require": {//adding our package name to laravel's composer.json
...,
"gandalf/test_pack": "*"//package's name
},
...,
"repositories": [
{
"type": "artifact",
"url": "D:/test_pack"
}
]
}
Method II(My Favorite method, You have to initialize your package directory as git local repository using git init and then git add . and git commit -m "your message")
1) initialize the package directory as git directory and commit all your changes to the local repository
(let's say D:/test_pack is the directory that contains your package(src/ directory and composer.json))
go to D:/test_pack directory and run these commands
git init
git add .
git commit -m "your message for this commit"
2) In your packages composer.json file add minimum-stability
{
"name": "gandalf/test_pack",
"description": "some desc",
"authors": [
{
"name": "gandalf the grey",
"email": "fake#yahoo.com"
}
],
"minimum-stability": "dev",//setting minimum-stability
"require": {
//dependencies that your package needs
},
"autoload": {
"psr-4": {
"Gandalf\\BotPack\\": "src/"
}
}
}
3)In laravel's composer.json file require the "dev-master" of your package
{
...,
"require": {
...,//some dependencies that laravel needs
"gandalf/test_pack": "dev-master"//requiring dev-master from repository
},
"repositories": [
{
"type": "git",
"url": "D:/test_pack"//path of the local repository directory which contains your package
}
]
}
To any Laravel project load local packages. which is stored in your machine.
In laravel's (Project) composer.json file add
"autoload": {
"psr-4": {
"YourPackage\\Namespace\\": "./local_Package_path/src"
}
},
and fire command in Laravel Project directory
composer dump-autoload
Optional
If package is still not available in your Project. then
Register your package's Service Provider.
To register your service provider, you just need to add an entry to the array of service providers in the config/app.php file.
'providers' => [
/*
* Laravel Framework Service Providers...
*/
...
YourPackage\Namespace\PackageServiceProvider::class,
],
Hope now your package loaded successfully in your laravel project.

Load vendor dependencies with composer.json

I have recently forked robmorgan/phinx project and modified the composer.json file in my project to use the forked version:
{
"name": "...",
"description": "...",
"repositories": [
{
"type": "package",
"package": {
"name": "lube8uy/phinx",
"version": "master",
"source": {
"url": "https://github.com/lube8uy/phinx.git",
"type": "git",
"reference": "master"
}
}
}
],
"require": {
"php": ">=5.3.0",
"lube8uy/phinx": "dev-master"
}
}
First question: additional vendors
Now, when I load the composer.json file in my project I get this forked version correctly.
What I don't know is how to load the dependencies from the phinx project itself:
https://github.com/lube8uy/phinx/blob/master/composer.json
If I use the original packagist source everything works fine and I got all the dependencies, but now that I use my own repository I can't get them.
Second question: updates
How can I receive the modifications I made to my github source?
I made some modifications, pushed them to the correct branch, then I run composer update but nothing was updated... what am I doing wrong?
Thank you very much
For your first question:
Try to require it as a VCS repository (Version Control System, see composer doc on vcs repositories), like the following:
{
"name": "...",
"description": "...",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/lube8uy/phinx"
}
],
"require": {
"php": ">=5.3.0",
"robmorgan/phinx": "dev-master"
}
}
It now requires the package robmorgan/phinx which is found at https://github.com/lube8uy/phinx which is the desired fork. It still has the original name robmorgan/phinx but is found at a different location.
It still has the same name because of the package name in its composer.json. If you want to change the name to lube8ye/phinx, change it in the composer.json in the fork.
For your second question:
The changes made in a package you require via composer should be updated automatically when you execute php composer.phar update in your project. If this does not work, try to force composer to require a specific commit by adding the commit hash after dev-master in your require section like so:
"require": {
"robmorgan/phinx": "dev-master#1234abcd"
}
Whereat 1234abcd is the hash of the desired commit.
Also: Try clearing composer's cache by deleting the folders content to avoid loading a cached version (see composer doc on COMPOSER_CACHE_DIR)

Composer ignoring zip dependecies' composer.json file

I'm using Composer for a project that needs to handle some dependencies but I got a really weird issue. Composer is ignoring the composer.json file contained in child packages.
My project needs to retrieve some custom zip packages, in these packages a composer.json file defines other requirements. The repositories of these requirements are declared in the root composer.json file since Composer cant recursively fetch repositories.
The thing is that after my zip package is downloaded, unpacked and placed in the vendor dir, composer totally ignores its composer.json where other requirements are defined...
The zip archive is something like this:
/dir1
/dir2
file1
file2
composer.json
To give you an idea this is how my root composer.json looks like:
{
"name": "myproject/project",
"type": "library",
"repositories": [
{
"packagist" : false
},
{
"type": "package",
"package": {
"name" : "giulianobundles/mybundle",
"version" : "1",
"dist": {
"url": "http://url/to/zip/file",
"type": "zip"
}
}
},
{
"type": "package",
"package": {
"name" : "giulianobundles/mybundlerequirement",
"version" : "1",
"dist": {
"url": "http://url/to/zip/file",
"type": "zip"
},
}
},
],
"require": {
"php": ">=5.3.2",
"giulianobundles/mybundle": "*"
},
"autoload": {
"psr-0": {
"config": "./"
}
},
}
and the bundle's composer.json package looks like
{
"name": "giulianobundles/mybundle",
"type":"library",
"require": {
"giulianobundles/mybundlerequirement": "1"
}
}
Mybundle package get succesfully installed but its composer.json file is totally ignored. Any idea? What am I missing?
Indeed, Composer will not recursively look at composer.json files in the file system. It needs to see the composer.json files in the repository. The way it usually works is that a package has a git or svn URL somewhere. Composer will fetch, for instance, git://<host>/<package>/composer.json directly from the repository to figure out that package's dependencies before it's even installed to calculate the overall dependencies.
In your case, you are defining a package inline in your own composer.json file. This is used instead of a composer.json file in the dependency. This means Composer takes the "package": { ... } to be the canonical composer.json file for that package, it will not look into the code itself; especially not after unpacking it. It treats the Zip file as if it had no composer.json file of its own.
Define the dependencies in the "package": { ... } or host the code in a version control system from which Composer can fetch the composer.json file.

Categories