Component-based development with composer - php

Let's say I want to write a new application.
/workspace/exampleapp/
.git
src/
vendor/
app/
component1/
.git
src/
composer.json
component2/
.git
src/
composer.json
composer.json
I have three git repositories. They have no remotes. I also have three composer.json files.
/workspace/app/composer.json
{
"name": "app/app",
"type": "project",
"license": "MIT",
"require": {
"app/component1": "dev-master",
"app/component2": "dev-master"
},
"autoload": {
"psr-4": {"app\\": "src/"}
}
}
/workspace/app/vendor/app/component1/composer.json
{
"name": "app/component1",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {"app\\": "src/"}
}
}
/workspace/app/vendor/app/component2/composer.json
{
"name": "app/component2",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {"app\\": "src/"}
}
}
If I run composer update in the project root I receive the error The requested package app/component1 could not be found in any version, there may be a typo in the package name.
What do I have to change to make it work? Is there a way without moving the components directories out of the vendor directory or creating remote repositories?
Thank you!

I think you are suffering from the XY problem - I'm going to pretend that you actually asked "How can I setup a project with Composer with the following requirements?"
Be able to work without a remote Git server i.e. be able to commit and push locally.
Be able to commit code for the components separately to the commits to the main project.
Be able to edit the code in the vendor directories for your repositories, and commit from those directories.
In which case the answer is, setup your directories like this:
/workspace/app/
composer.json
src/
/workspace/components/
component1/
composer.json
src/
component2/
src/
composer.json
Setup each of your component's composer file like this:
/workspace/components/component1/composer.json
{
"name": "app/component1",
"type": "library",
"license": "MIT",
"autoload": {
"psr-4": {"app\\": "src/"}
}
}
Tell your the composer.json file for your app to use the components directories as local git repositories.
/workspace/app/composer.json
{
"name": "app/app",
"type": "project",
"license": "MIT",
"require": {
"app/component1": "dev-master",
"app/component2": "dev-master"
},
"autoload": {
"psr-4": {"app\\": "src/"}
},
"repositories": [
{
"type": "vcs",
"url": "/workspace/components/component1"
},
{
"type": "vcs",
"url": "/workspace/components/component2"
}
],
}
When you do the first "composer update" you should run it with the option composer update --prefer-source. That will force composer to do a git clone for the code, rather than downloading just a zip-ball and extracting it.
(Adding --prefer-source may not be required, it seems composer may do clone by default when fetching from a local directory repository).
You will now be able to edit the code for the components in the vendor directory, be able to commit it separately to the app code, as well as be able to push it to 'remote' git repository at /workspace/components/component1/.

Related

composer.json does not contain a valid json

there is a syntax error in my composer.json file but I just can't seem to find the error. I already have a Laravel object on top of the file, but I also want to add Goaop, like the following code.
how can I do it? thank you
//newly added code
{
"name": "goaop/goaop-laravel-bridge",
"description": "Integration bridge for Go! AOP framework",
"type": "library",
"keywords": ["bridge", "laravel", "aop", "php", "aspect"],
"require": {
"goaop/framework": "^1.0|^2.0",
"laravel/framework": "^5.0"
},
"license": "MIT",
"authors": [
{
"name": "Lisachenko Alexander",
"email": "lisachenko.it#gmail.com"
}
],
"autoload": {
"psr-4": {
"Go\\Laravel\\GoAopBridge\\": "./src"
}
}
}
Looks like you just copied the package's composer.json and pasted it to the bottom of yours. That is not how you install packages.
From your command line run:
composer require goaop/goaop-laravel-bridge
This will update your composer.json and .lock files and install the package.

How do I get my composer package autoloaded properly?

I have created a package to separate out business logic into easier to distribute modules. The composer file looks like this:
{
"name": "aggiq/johnny-cash",
"description": "A collection of controllers, models, migrations, and tests for a phonebanking backend.",
"license": "MIT",
"authors": [ ... ],
"require": {
"illuminate/database": ">=5.5"
},
"require-dev": {
"fzaninotto/faker": "~1.4"
},
"autoload": {
"psr-4": {
"Johnny\\Phonebanking\\": "src/"
}
}
}
And our source files are indeed in src/:
src/Controllers/PhonebankController.php
src/Models/Phonebank.php
...
I saved and pushed this to our gitlab repo, and then included it as a dependency in a test project:
{
...,
"repositories": [{
"type": "package",
"package": {
"name": "aggiq/johnny-cash",
"version": "0.1",
"type": "package",
"source": {
"url": "gitlab url",
"type": "git",
"reference": "dev"
}
}
}],
"require": {
"aggiq/johnny-cash": "*",
},
...
}
And when I do composer update, it successfully grabs the project and downloads it into the vendor folder:
vendor/aggiq/johnny-cash/Controllers/PhonebankController.php
...
However, when I look in the test project's autoload_psr4.php, it's not there. Is there a step I missed?
Edit: updates the directories to have capital letters to match the namespaces, and here is the generated PSR4 php file:
<?php
// autoload_psr4.php #generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);
You have registered autoloading at your package's composer.json correctly:
"autoload": {
"psr-4": {
"Johnny\\Phonebanking\\": "src/"
}
}
This means, any class in Johnny\Phonebanking namespace will be in src directory. E.g.:
Johnny\Phonebanking\SomeClass => src/SomeClass.php
Johnny\Phonebanking\SomeNamespace\AnotherClass => src/SomeNamespace\AnotherClass.php
As you can see, it has to respect CapitalLetters.
Saying that, you should correct first letters of your directories, from:
src/controllers/PhonebankController.php
src/models/Phonebank.php
to
src/Controllers/PhonebankController.php
src/Models/Phonebank.php
I have solved it. We needed to do two things.
The repository type specified in the parent pacakge should be vcs not package since we are loading from a git server:
"repositories": [{
"type": "vcs",
"url": "git#xxx.git"
}]
The package type in the child package should be library:
"type": "library"
Once those two changes were made, composer update installed not only the child package but also its dependencies, proving it is being recognized by composer.

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.

How to run library with composer?

I'm trying to install this github repo to my project (running on codeigniter). The steps I'm doing is very simple:
{
"name": "project",
"description": "",
"license": "MIT",
"require": {
"php" : ">=5.3.0",
"blockchain/blockchain" : "1.*",
"ext-curl": "*"
},
"require-dev": {
}
} // composer.json
and run php composer.phar update. So the package installs but I can't use it in my project - I don't think its autoloaded. /vendor/autoload.php is required in my index.php. When I try it with different package for test purposes (kriswallsmith/buzz) - it works. So what I'm doing wrong?
Also I checked my vendor/composer/installed.json and I see this:
[
{
"name": "blockchain/blockchain",
"version": "v1.0",
"version_normalized": "1.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/blockchain/api-v1-client-php.git",
"reference": "c219b9b00778cf6c025628bd34fd6543922fe81b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/blockchain/api-v1-client-php/zipball/c219b9b00778cf6c025628bd34fd6543$
"reference": "c219b9b00778cf6c025628bd34fd6543922fe81b",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3.0"
},
"time": "2015-02-03 18:34:11",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"Blockchain\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Blockchain API client library",
"homepage": "https://github.com/blockchain/api-v1-client-php",
"keywords": [
"bitcoin",
"blockchain"
]
}
]
and my function where I'm trying to use this lib:
private function __check_btc_balance()
{
error_reporting(E_ALL);
$Blockchain = new \Blockchain\Blockchain(PAYMENTS_BTC_API_CODE);
}
Have you followed the installation steps?
Basically there are some differences from common composer packages. Over here it says download the source code and run composer install from it's own folder
Then include the autoloader file from the folder of the downloaded files so you will have somewhere a folder Blockchain/vendor/autoload.php to include
Download the source or clone the repository. This php library works
with the Composer package manager. Navigate to the root of the
repository and run
$ composer install
This will create the /vendor folder in the repository root. In the php
source, simply:
// Include the autoload.php from its vendor directory require
'vendor/autoload.php'
// Create the base Blockchain class instance
I've seen ...
"autoload": {
"psr-4": {
"Blockchain\\": "src/"
}
},
I always keep all my code in src\Vendor\Project\Filename.php and composer autoloader works with this. Try to add this lines of code:
"autoload": {
"psr-0": {
"": "src/"
}
},

ZF2 Modules & external dependencies

I'm not clear on what the best practice is for including external libraries in a custom module that I plan on distributing.
Normally I'd place the external library under the application's vendor directory. But I want to ensure that all dependencies are met when I distribute my custom module (i.e. I don't want to force people to manually download the dependency into their app's vendor directory).
Is the correct practice to include a vendor directory under the module directory as per the the following?
/application_dir
/vendor
/module
/my_module
/vendor
Use composer, you can find documentation here:
Composer Documentation
Basically you would modify the file composer.json in the root of your application and add your dependencies in the require section:
{
"name": "zendframework/skeleton-application",
"description": "Skeleton Application for ZF2",
"license": "BSD-3-Clause",
"keywords": [
"framework",
"zf2"
],
"homepage": "http://framework.zend.com/",
"require": {
"php": ">=5.3.3",
"zendframework/zendframework": "2.2.*",
"doctrine/common": "dev-master",
"zendframework/zendpdf": "2.*",
"zendframework/zendservice-recaptcha": "2.*",
"thiagoalessio/tesseract_ocr": ">= 0.1.2",
"zf-commons/zfc-user": "dev-master"
// add your requirements here**
}
}
if the dependancy is on a private github repository, you can add it like this:
{
"require": {
"vendor/my-private-repo": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "git#bitbucket.org:vendor/my-private-repo.git"
}
]
}
Don't forget to do composer.phar update after your done adding them.

Categories