| 1 | 1 | new file mode 100644 | 
| ... | ... | @@ -0,0 +1,119 @@ | 
| 0 | +--- | |
| 1 | +layout: post | |
| 2 | +title: "Dependency management in PHP projects #2" | |
| 3 | +date: 2013-12-08 00:25 | |
| 4 | +comments: true | |
| 5 | +categories: [webdev, php] | |
| 6 | +cover: /images/cover/avatar.png | |
| 7 | +keywords: php, composer, bundle, versions, dependencies, packages, libraries | |
| 8 | +description: | |
| 9 | +--- | |
| 10 | + | |
| 11 | +In the last [article](/2013/11/24/dependency-management-in-php-projects/) about | |
| 12 | +dependency management I've explained why we, PHP programmers, need [composer](http://getcomposer.org/) | |
| 13 | +and why you should use it in your PHP projects. | |
| 14 | + | |
| 15 | +Let's dig deeper in composer internals. | |
| 16 | + | |
| 17 | +# Where can I find packages for composer? | |
| 18 | + | |
| 19 | +Many of packages which we can use as project dependencies can be found on [packagist](https://packagist.org/). | |
| 20 | + | |
| 21 | +# Dependency versioning | |
| 22 | + | |
| 23 | +Let's say our project depends on [Twig](http://twig.sensiolabs.org/) library. | |
| 24 | +The ```require``` section in ```composer.json``` file will look like this: | |
| 25 | + | |
| 26 | +{% codeblock lang:json %} | |
| 27 | +	"require": { | |
| 28 | + "twig/twig": "1.12.*" | |
| 29 | + } | |
| 30 | +{% endcodeblock %} | |
| 31 | + | |
| 32 | +The file says we want Twig version at least 1.12.0. Composer will install the newest | |
| 33 | +minor version (e.g. 1.12.1 or 1.12.3) of major version 1.12. We'll never get Twig | |
| 34 | +1.11 or Twig 1.13 or Twig 2.0. | |
| 35 | + | |
| 36 | +We can define an exact version of Twig like this: ```"twig/twig": "1.12.1"```. | |
| 37 | + | |
| 38 | +Maybe we want any newest development version. It's simple: ```"twig/twig": "dev-master"```. | |
| 39 | +Now composer will install newest bleeding-edge version from ```master``` branch | |
| 40 | +from Twig's [Git repository](https://github.com/fabpot/Twig). The used schema | |
| 41 | +is: ```dev-<branch>```. | |
| 42 | + | |
| 43 | +# Using custom dependencies | |
| 44 | + | |
| 45 | +If you have your own libraries you want to use in a project, add ```repositories``` section | |
| 46 | +to the ```composer.json```. It contains array of | |
| 47 | +<abbr title="Version Control System">[VCS](http://en.wikipedia.org/wiki/Revision_control)</abbr> | |
| 48 | +repositories. | |
| 49 | + | |
| 50 | +Let's say you want to use a library hosted on github. Then the ```repositories``` | |
| 51 | +section can look like this: | |
| 52 | + | |
| 53 | +{% codeblock lang:json %} | |
| 54 | + "repositories": [ | |
| 55 | +		{ | |
| 56 | + "type": "git", | |
| 57 | + "url": "https://github.com/vendor/example.git" | |
| 58 | + } | |
| 59 | + ] | |
| 60 | +{% endcodeblock %} | |
| 61 | + | |
| 62 | +In ```type``` field we said it's a Git repository and an address of the repository | |
| 63 | +is defined in ```url``` field. | |
| 64 | + | |
| 65 | +Then, you can edit the ```require``` section: | |
| 66 | + | |
| 67 | +{% codeblock lang:json %} | |
| 68 | +	"require": { | |
| 69 | + "twig/twig": "1.12.*", | |
| 70 | + "vendor/example": "dev-master" | |
| 71 | + } | |
| 72 | +{% endcodeblock %} | |
| 73 | + | |
| 74 | +Now ```composer update``` will fetch code of "example" library from ```https://github.com/vendor/example.git``` | |
| 75 | +repository. | |
| 76 | + | |
| 77 | +# How my project knows about installed dependencies? | |
| 78 | + | |
| 79 | +Composer creates ```autoload.php``` file in ```vendor``` directory. The file takes care | |
| 80 | +of *dynamic* autoloading of all dependencies. Dynamic means all required files are loaded | |
| 81 | +when they are needed. If we had defined 20 dependencies, it would be very inefficient | |
| 82 | +and slow to load all files. | |
| 83 | + | |
| 84 | +When some dependency class is used for the first time, composer's Autoloader gets called | |
| 85 | +and tries to find and load needed files. | |
| 86 | + | |
| 87 | +I believe an example below enlightens the question. All you need to do is to include | |
| 88 | +```autoload.php``` file in your project. | |
| 89 | + | |
| 90 | +{% codeblock index.php lang:php %} | |
| 91 | + <?php | |
| 92 | + | |
| 93 | + // load autoload.php | |
| 94 | + require 'vendor/autoload.php'; | |
| 95 | + | |
| 96 | + // how many files has been loaded so far | |
| 97 | + echo "Number of loaded files: " . count(get_included_files()) . "\n"; | |
| 98 | + | |
| 99 | + // can use Twig class | |
| 100 | + $loader = new Twig_Loader_String(); | |
| 101 | + | |
| 102 | + echo "Number of loaded files: " . count(get_included_files()) . "\n"; | |
| 103 | +{% endcodeblock %} | |
| 104 | + | |
| 105 | +The example is very simple, I just wanted to show dependency autoloading **just works**. | |
| 106 | +By the way, the output is: | |
| 107 | + | |
| 108 | + Number of loaded files: 6 | |
| 109 | + Number of loaded files: 9 | |
| 110 | + | |
| 111 | +First time a counter was called there were loaded only composer files. Next time | |
| 112 | +composer loaded more files required by Twig. | |
| 113 | + | |
| 114 | +Very interesting topic about autoloading of your own code is explained on composer | |
| 115 | +official [guide](http://getcomposer.org/doc/01-basic-usage.md#autoloading). | |
| 116 | + | |
| 117 | + | |
| 118 | +*This article was also published on my school [blog](http://cinan.blog.matfyz.sk/p106605-dependency-management-in-php-projects-#2).* | |
| 0 | 119 | \ No newline at end of file |