composer helpdesk

Post on 19-Jul-2015

586 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

PHP Usergroup Munich2015-01-28

HELPDESK

About me

● Sven Rautenberg● Developing with PHP for >15 years now● Currently working for Kabel Deutschland

– Doing API stuff for ordering GUI interfaces

– aka the PHP middleware in front of the Java middleware

● I do have a past at SELFHTML (selfhtml.org)● Some activity at Stackoverflow for PHP, Log4php and Composer● Twitter: @SvenRtbg

Questions

● Please ask at once– anything directly related to the current slide

– me not cleanly explaining stuff, talking too fast or incomprehensible

● Try to wait until the end, Q&A session– anything broader, which may be answered by an upcoming slide

– your own examples of Composer usage, failure and fixes

How to generally use it

● On 1 slide, because you already know it (or should):– getcomposer.org is the main page for software and documentation

– downloading Composer from there is a one line CLI command

curl -sS https://getcomposer.org/installer | php– mind the security implications of this command (discussed later)

– for convenience: symlink/rename/move the downloaded phar file to composer and make it available in your $PATH

– This should work anywhere now:

composer –-help

Now let Composer do the work for you

● You have an existing project, or want to start a new● Go to the root folder (top level GIT folder etc.)● Use the command line

composer init– This asks a lot of questions, with sensible default answers.

– creates the initial composer.json in less than a minute.

vagrant@vbox /home/vagrant/myapplication $ composer init

Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [root/composer-demo]: fancy-devshop/myapplicationDescription []: Does useful stuff for everybody.Author [Jane Doe <jane.doe@fancy-devshop.example>]:Minimum Stability []:License []: proprietary

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]? noWould you like to define your dev dependencies (require-dev) interactively [yes]? no

{ "name": "fancy-devshop/myapplication", "description": "Does useful stuff for everybody.", "license": "proprietary", "authors": [ { "name": "Jane Doe", "email": "jane.doe@fancy-devshop.example" } ], "require": {}}

Do you confirm generation [yes]?vagrant@vbox /home/vagrant/myapplication $

Epic win!

● You just enabled your project to make use of Composer– it has a name attached to be identified.

– automatic detection of tagged versions and branches in it's repository

– started the list of contributors with the configured GIT default info● probably works with the other supported VCS as well

– the license is optional, “proprietary” is for non-open source● we are not going into details for this here

● Everything you did until now allows others to use your project, including yourself. We'll see some use cases later.

Using others' code for your project

● The obvious usage: Include useful libraries● Main page to search: packagist.org● Hint:

– command line is easier than fiddling with the composer.json

composer require zendframework/zend-cache:~2.2

composer require --dev symfony/console:~2.3– and barely more typing

– will install the library if a version matches everything else, or roll back

– we get to the version details later on

How to install a foreign library

1. Find a suitable library– It should do what you want (useful, secure, nice defaults etc.)

– It may match your style of programming

– It should have an amount of documentation that you are happy with

– It may have a reasonable number of installs according to Packagist

– It should (read as: MUST) have tagged releases as version numbers.

– The stability of the tagged releases don't matter as long as you can live with it.

– Reminder: Versions do come later in this talk.

How to install a foreign library

2. Run Composer to fetch the code.composer require vendor/library:~1.0

3. Include the Composer autoloader in your bootstrappingrequire “vendor/autoload.php”;

4. Use the library classes, don't care about how to load them.

5. Profit!

Using Composer for your own project

● Using the autoloading of Composer for your own project!● Multiple choices to make it work:

– PSR-4

– PSR-0

– classmap

– files

● Every existing code should be loadable via Composer somehow

PSR-4

● Works for classes in namespaces only!● Allows for shallow directory structures● This autoload definition in composer.json

“Namespace\\” : “src/”

will autoload this class namenew \Namespace\Adapter\Foobar()

in this locationsrc/Adapter/Foobar.php

PSR-4

● Works for classes in namespaces only!● Allows for shallow directory structures● This autoload definition in composer.json

“Namespace\\” : “src/”

will autoload this class namenew \Namespace\Adapter\Foobar()

in this locationsrc/Adapter/Foobar.php

Escapin

g a ba

cksla

sh

PSR-4

● Works for classes in namespaces only!● Allows for shallow directory structures● This autoload definition in composer.json

“Namespace\\” : “src/”

will autoload this class namenew \Namespace\Adapter\Foobar()

in this locationsrc/Adapter/Foobar.php

No namespace in path

PSR-0

● Works for classes in namespaces and Under_Scored_Classes!● This autoload definition in composer.json

“Namespace\\” : “src/”

will autoload this class namenew \Namespace\Adapter\Foobar()

in this locationsrc/Namespace/Adapter/Foobar.php

PSR-0

● This autoload definition in composer.json“Under_Scores_” : “src/”

will autoload this class namenew Under_Scores_Adapter_Foobar()

in this locationsrc/Under/Scores/Adapter/Foobar.php

PSR-0 What to avoid!

● This autoload definition in composer.json“” : “src/”

will autoload this class namenew Under_Scores_Adapter_Foobar()

in this locationsrc/Under/Scores/Adapter/Foobar.php

● Any will try to locate all other classes under src as well.● Failing to find the file here, will search in the next possible

location, but with useless file system lookups – is slow!

PSR-0 What to avoid!

● A real example from this morning:– We are using a modified Zend Framework 1 with this autoloading:

“Zend” : “src”– and the stock Zend Framework 2 components

● Loading this class from ZF2new \Zend\EventManager\SharedEventManager()

will incorrectly detect this file as existing from ZF1src/Zend/Eventmanager/SharedEventManager.php

– which contains

class Zend_EventManager_SharedEventManager …

PSR-4 & PSR-0 summary

● Prefer PSR-4 if possible– When you are using namespaces, use PSR-4!

● Aim for the longest possible or reasonable prefix!– Have an underscore or backslash at the end of the prefix!

– You can define multiple entries for different prefixes in your code base

“Models\\”: “lib/models/”

“Database_”: “lib/databases/”– If the same prefix is also used in a different code base, make it longer.

● PSR-0 can be converted to PSR-4 for namespaced classes“Namespace\\” : “src/” <=> “Namespace\\”: “src/Namespace/”

Classmap

● If your code doesn't fit into PSR-4 or PSR-0 scheme.● Composer will scan all directories for PHP files containing

classes/interfaces/traits and will add them to a lookup array (aka classmap).

● Newly created files won't be added automatically! Annoying.composer dump-autoload

● Good for old code bases that you don't actively work on, but can't convert to PSR-* either.

Classmap

● This definition“classmap”: [“src1/path”, “src2/path”]

will search for auto-loadable stuff in both directories.● Try to scan as few directories as possible - it will slow down any

Composer command that creates a new autoloader.● Don't impose it on everyone for PSR-0 or PSR-4 code because

“Classmaps are faster” - let them decide themselves withcomposer dump-autoload –optimize

● Performance discussion on Stackoverflow (link)

Files

● The final method if all else fails.● Composer will always include the files you declare here, the

code is always available even if not needed.– Try to avoid doing slow things in these files.

● Use this for your functions that are not inside classes– Autoloading for functions doesn't exist yet.

– Maybe moving the functions to a class and call them statically instead.

● You may also add your own autoloading function here in case you cannot make classmap work for you.

... "require": { "zendframework/zend-cache": "~2.2" }, "require-dev": { "symfony/console": "~2.3" }, "autoload": { "psr-4": { "Fancy\\": "src/fancystuff/" "Devshop\\: "library/Devshop/" }, "psr-0": { "Devshop_": "library/legacy/" }, "classmap": [ "library/non-fancy-stuff/" ] }}

Epic win!

● Your own code is now autoloaded via Composer alongside all external libraries.

● All classes you might use anywhere in the code are available without first loading their code!

● You are only one step away from creating your own library that you can use in multiple of your own projects!

Versions and Composer

● Composer does not impose any specific version scheme besides the fact that it has to be numeric.– No code names as version identifiers.

– One single integer number should work, but is uncommon.

● However Composer suggest to use semantic versioning and has convenient operators for this– Tilde operator: ~2.3

– Caret operator: ^4.4.2

Semantic versioning: X.Y.Z

● Independent integers x,y,z, no float, more than one digit possible– Example 1.9.0 → 1.10.0 → 1.11.0

● Bugfixes: increase Z● Compatible new feature: increase Y● Incompatible new releases: increase X● Suffix like “alpha”, “beta”, “RC” allowed to denote lesser stability

– Denotes a version before the original, i.e. 1.0.0-alpha < 1.0.0

● More details: semver.org

Tagging your library

● Try to stick to semantic versioning as closely as possible– It will make your life so much easier!

● 1.0 and 1.0.0 is semantically the same, but a different VCS tag!– Accidentially re-tagging 1.0 as 1.0.0 cannot be detected by your VCS

– Haven't checked what Composer will do in this case.

– Best practice: Always three digits

● Do use alpha, beta, RC for versions undergoing development● Avoid using 0.9.x for development and 1.0.0 for release

– understood as an incompatible change, probably wrong

Adding your library to your own project

● Assume you have tagged your first version 1.0.0– You want to use this version only

composer require fancy-devshop/library:1.0.0– You want to allow updating to later bugfixes

composer require fancy-devshop/library:1.0.*– You want to allow updating to later compatible features

composer require fancy-devshop/library:~1.0

composer require fancy-devshop/library:^1.0.0● How to make your library known to Composer without publishing

it on packagist.org: Wait a few slides.

Version requirements

● When you update all your dependencies, you runcomposer update

● The version requirement affects what may be installed– 1.0.0 → exactly this version

– 1.0.* → any version starting with 1.0 – allows all later patches

– ~1.0 → equivalent to >=1.0, <2.0, allows for compatible updates

– ^1.0.0 → equivalent to >=1.0.0, <2.0, allows for compatible updates

● Not really useful– >=1.0.0 → allows for incompatible updates to versions 2 and beyond

Difference between ~ and ^

● ^ is the newest addition from 2014-12-08– “^1.0.2” → >= 1.0.2, < 2.0, installs at least the patch level mentioned

– “^0.8.1” → >=0.8.1, <0.9, is more defensive with unstable versions

● Doing almost same with ~ isn't the same– “~1.0.2” → => 1.0.2, <1.1 won't include compatible updates

– “~1.0, >=1.0.2” → minimum patch level needs two constraints

– No special case for unstable versions

● Use ~ or ^ for your version requirements!– Unless the external software does not honor semantic versioning.

{ "name": "fancy-devshop/myapplication", "description": "Does useful stuff for everybody.", "license": "proprietary", "authors": [ { "name": "Jane Doe", "email": "jane.doe@fancy-devshop.example" } ], "require": { "fancy-devshop/library": "^1.0.2" }, "autoload": { "psr-4": { "Devshop\\: "library/Devshop/" }, "psr-0": { "Devshop_": "library/legacy/" } }}

{ "name": "fancy-devshop/library", "description": "Increases fancyness.", "license": "proprietary", "authors": [ { "name": "Jane Doe", "email": "jane.doe@fancy-devshop.example" } ], "require": {}, "autoload": { "psr-4": { "Fancy\\: "src/" } }}

Epic win!

● Our application is using Composer for autoloading, and adding internal and external libraries.

● Our internal library is using Composer for autoloading.– It may use Composer for it's own internal and external dependencies.

● The library has releases that are simply tags in the VCS.● The application can update everything based on version

requirements that SHOULD be compatible to the initial version.– You DO have tests to check if everything works after an update?

What is still missing?

● How to publish your internal libraries without making them public on packagist.org?

● How to develop a library and use a dev version in the application at the same time?

● How to figure out what dependencies and sub-dependencies are really included in a package?

● How to define dependencies that are only used for development?

● What about security?

Publishing the quick way

● Composer by default only asks packagist.org as repository.● You can add your own repository in composer.json:

“repositories”: [

{ “type”: “vcs”, “url”: “ssh://git@fancy-repo.example” }

]● Composer will then ask for the composer.json in this repo (in all

branches and tags), check whether it has a package name you want to use, and clone or download the correct version.

● Drawback: Does only work at the top level (i.e. your application)– Does not work recursively in libraries you require (with good reasons)

Publishing the easy way

● You need a local instance of either one of these:– Satis (generates static files and dumps downloadable versions)

– Packagist (available for local hosting, dynamic updates)

– Toran Proxy (license costs support Composer development)

● You add this instance location to all your composer.json files“repositories”: [

{ “type”: “composer”,

“url”: “http://fancy-repos.example/satis-files” }

]

Publishing the “easy” way

● You configure your local Packagist clone accordingly.– It should fetch all necessary data from your local repositories.

– It will publish these at the location given.

● Composer will first read from this local repo before going to packagist.org– Works recursively, because the packagist clone is defined at top level

in every package.

– All local packages are known by the clone.

– All external packages are known by packagist.

Satis example

● Satis is available on Github● Configuration example creates downloadable ZIP packages for

each version. Composer will cache these locally.● Run the Satis CLI command every time you need the static files

updated.● Lesser known feature: Composer allows to link to other

composer-repositories

{ "name": "Fancy Devshop", "homepage": "https://fancy-devshop.example/satis-files", "repositories": [ { "type": "vcs", "url": "ssh://git@fancy-gitserver.example:2222/repos/library.git" }, { "type": "composer", "url": "https://fancy-devshop.example/released-fairy-dust" }

], "require-all": true, "archive": { "directory": "dist", "format": "zip", "prefix-url": "https://fancy-devshop.example/satis-files", "skip-dev": true }, "twig-template": "views/index-fancy.html.twig"}

Epic win!

● The application's dependencies can be loaded from the local Satis or from Packagist.

● New versions of local libraries will be detected and published locally (manually, with a cronjob, with a repo hook).

● This should be all you need to finally be able to deploy!– I won't go into deployment details now, but as a hint:

composer install --no-dev

How to use a package under development?

● Tagging every single commit is not helpful.● Add a branch with a version alias

composer require \

"fancy-devshop/library:dev-master as 2.0.0-dev"● Or create a branch resembling the target version

git branch 2.0.x

composer require "fancy-devshop/library:~2.0@dev"– Update regularly

composer update● Upgrade the version requirement after release.

How to get an overview of used packages?

● The composer.lock file has every package and version recorded that is being used. Always commit this file!

● Reading it isn't nice, but you can see some details.● What about a picture? Use clue/graph-composer ● Needs graphviz installed to render the pictures.● Shows all the dependencies and version requirements.

How to treat code used for development only?

● Add stuff like PHPUnit, Mockery, as a dev dependencycomposer require --dev phpunit/phpunit:~4.4

● Add your own development code as dev autoloading:“autoload-dev”: {

“psr-4”: { “Tests\\”: “tests/helpers/” }

}● This will not be added or installed when you run with --no-dev

Security considerations

● Composer currently has no code signing or security layer!● There is some security coming from GIT commit ids and using

HTTPS.● Assume everything outside your own environment is

compromised and broken if you really have sensitive applications that undergo audits.

● Think about cloning external software into local repos, then treating them as local software.

● You can disable using Packagist in composer.json“repositories”: [ { “packagist”: false } ]

Thank you!

● And now it's time for all your questions!

● Slides will be online soon.

● Contact me or ask questions here:– Twitter: @SvenRtbg

– StackOverflow: Sven

top related