ZF2 Modules & external dependencies - php

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.

Related

Composer does not respect installer-paths

Here is the scenario:
I have two projects driven by composer. The first one looks like this:
{
"name": "myusername/composer_test",
"description": "Composer project for CircleK Drupal 8",
"type": "project",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Name Surname",
"role": "webdeveloper"
}
],
"repositories": [
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"php": ">=5.6",
"composer/installers": "^1.2",
"drupal-composer/drupal-scaffold": "^2.5",
"drupal/core": "^8.7.0",
"vlucas/phpdotenv": "^2.4",
"webflo/drupal-finder": "^1.0.0",
"webmozart/path-util": "^2.3",
"zaporylie/composer-drupal-optimizations": "^1.0"
},
"minimum-stability": "dev",
"prefer-stable": true,
"extra": {
"installer-paths": {
"web/core": ["type:drupal-core"]
}
}
}
Second one requires the first one and it's pretty straight forward:
{
"name": "user/site",
"description": "Composer for Site",
"type": "project",
"license": "GPL-2.0-or-later",
"authors": [
{
"name": "Name Surname",
"role": "webdeveloper"
}
],
"repositories": [
{
"type": "git",
"url": "git#github.com:myusername/composer_test.git"
},
{
"type": "composer",
"url": "https://packages.drupal.org/8"
}
],
"require": {
"myusername/composer_test": "dev-drupal_only"
},
"minimum-stability": "dev",
"prefer-stable": true
}
As you can see the first one defines where drupal core should be placed at by defining installer-paths. It turns out that when I run composer install just for the first composer.json file drupal core ends up in ./web directory as should, however when I run composer install for second file it does download every package from first composer.json just fine, but drupal core ends up in main directory instead of ./web. I know I can put installer-paths into the last composer file and overwrite it, but that's not the point. I want first file to define where stuff should be place at.
The extra settings only work for the root package. Consider user/site requiring 2 different packages that both specifiy different installer paths. Which one should composer use and how should it know? By ignoring those settings, unless they are specified in your root composer.json, composer circumvents any surprises/problems.
There is a way around this, you can create a post-install script that determines the correct path for you, e.g. by checking if myusername/composer_test is installed and the variable is set. This is a bit similar to how Symfony's Install-Script in the SensioDistributionBundle used to do it. It provides a fallback to determine the right directory to use based on configs and folder structure (due to changes in how the default directory structure looks at ~2.8, e.g. moving app/console to bin/console).
You could write your own install script that inspects the installed composer packages. The downside is, that just like you now have to specify the extra config in your second composer.json, you will have to specify the install scripts, plus you have to write the install script itself. So it might be a lot of extra work without gaining a lot from it.

Laravel package development how do I use another facade in my package

I am creating my own Laravel package, in my package I have some views and I want to use the Form facade in one of my views, something like this: Form::open(). Is this possible, if so, how?
This is my composer.json:
{
"name": "thomasbird/laravel-cms",
"description": "A basic content management package that encapsulates some of the common functionality of a cms",
"type": "project",
"license": "MIT",
"authors": [
{
"name": "Thomas Bird",
"email": "godoploid#gmail.com"
}
],
"minimum-stability": "dev",
"require": {
"laravelcollective/html": "5.*",
"symfony/css-selector": "^3.2"
},
"require-dev": {
"symfony/dom-crawler": "2.8.*|3.0.*"
}
}
You need to specify any required packages within the require section of your composer.json.
For example, if you wish to use laravel collective's html helpers, in your package's composer.json, you can specify as follows:
"require": {
"php": "^7.0",
"laravelcollective/html":"^5.4.0",
...
...
...
So you can use any facades included within your required packages.

Composer not installing dependencies of Package

I have two projects. One is my application and the second one is an external module that I want to use in future apps.
I have created my external module on GitHub and included in the composer.json of my application.
My external module gets downloaded / cloned but the required dependencies are not installed by composer.
Here's composer.json of my application:
{
"name": "application",
"description": "Skeleton Application for ZF2",
"license": "BSD-3-Clause",
"keywords": [
"framework",
"zf2"
],
"homepage": "http://framework.zend.com/",
"require": {
"php": ">=5.5",
"zendframework/zendframework": "2.*",
"zf-commons/zfc-user": "1.4.4",
"doctrine/doctrine-orm-module": "~0.9.2",
"zf-commons/zfc-user-doctrine-orm": "1.0.*",
"zendframework/zend-developer-tools": "^0.0.2",
"username/GlideUser": "dev-master"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/username/GlideUser.git"
}
]
}
Here's composer.json of my external module:
{
"name": "username/glide-user",
"description": "Module For Zend Framework 2",
"type": "library",
"license": "BSD-3-Clause",
"homepage": "https://github.com/username/GlideUser",
"keywords": [
"zf2",
"zfc-user",
"bjyauthorize"
],
"authors": [
{
"name": "Haris Mehmood",
"email": "abc#outlook.com",
"homepage": "abc.com",
"role": "Developer"
}
],
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"php": ">=5.3.3",
"bjyoungblood/bjy-authorize": "1.4.0"
},
"autoload": {
"psr-0": {
"GlideUser\\": "src/"
}
}
}
When I run composer install or composer update I expect bjyauthorize package to gets installed, but composer ignore the dependency and install everything else.
What is it that I am doing wrong here.
Try updating the following line in your application composer.json from:
"username/GlideUser": "dev-master"
to:
"username/glide-user": "dev-master"
This way, what is being required matches the name of the external module, which is the name defined inside the external module's composer.json.
Although it does not look directly applicable to the dependencies of the external module not installing, it could be the cause.

Component-based development with composer

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/.

PHP & Composer, how do I combine composer.json files

Can someone explain how I'm supposed to use composer with a php. I have a composer.json file in my doc root that downloads the core packages for my project, but then when I want to add another project like google+ php sdk found here https://github.com/googleplus/gplus-quickstart-php/
what do I do with that composer.json file? do i combine them manually? Do I just download that composer.json into a different dir?
my current composer.json file looks like this
{
"name": "fuel/fuel",
"type": "metapackage",
"description": "The FuelPHP framework",
"keywords": ["framework"],
"homepage": "http://fuelphp.com",
"license": "MIT",
"authors": [
{
"name": "FuelPHP Development Team",
"email": "team#fuelphp.com"
}
],
"support": {
"irc": "irc://irc.freenode.org/fuelphp",
"forum": "http://fuelphp.com/forums"
},
"require": {
"php": ">=5.3.3",
"monolog/monolog": "1.5.*",
"fuelphp/upload": "2.0",
"omissis/php-cloudfiles": "dev-master",
"mustache/mustache": "*"
},
"suggest": {
"mustache/mustache": "Allow Mustache templating with the Parser package",
"smarty/smarty": "Allow Smarty templating with the Parser package",
"twig/twig": "Allow Twig templating with the Parser package",
"mthaml/mthaml": "Allow Haml templating with Twig supports with the Parser package"
},
"config": {
"vendor-dir": "fuel/vendor"
},
"minimum-stability": "dev"
}
The g+ composer.json file looks like
{
"name": "googleplus/quickstart",
"description": "This quick-start app is built in PHP and lets you get started with the Google+ platform in a few minutes.",
"license": "Apache-2.0",
"repositories": [
{
"type": "package",
"package": {
"name": "google/google-api-php-client",
"version": "0.6.2",
"dist": {
"url": "http://google-api-php-client.googlecode.com/files/google-api-php-client-0.6.2.tar.gz",
"type": "tar"
},
"autoload": {
"classmap": [
"src/"
]
}
}
}
],
"require": {
"silex/silex": "1.0.*#dev",
"twig/twig": ">=1.8,<2.0-dev",
"google/google-api-php-client": "0.6.2"
}
}
Simply add this into the require block of your original composer file:
"googleplus/quickstart": "*",
I have little experience with Composer, but I can tell you that when you require a lib, you add that lib to your main composer.json file. Upon installation or update, the new lib will be downloaded and its composer.json file will be read by Composer; its dependencies will be automatically downloaded, and so on.
So we could say you're not supposed to download your requirements manually, you have to use Composer for that, it will take care of it for you.

Categories