Composer is the de facto standard for installing packages in the PHP world. Packages are simply bundles of code that help kickstart an application. They let you build on the shoulders of giants and keep us from having to reinvent the wheel as they say.
There are all kinds of Composer packages listed at the official repository of packages Packagist. They offer all kinds of additional functionality, like Carbon which provides an elegant wrapper around PHP dates.
You can also download entire frameworks like Symfony.
Ruby’s take on Plug and Play Libraries
First off, Composer and it’s concept of packages are not included in PHP be default. They’re external, but so widely accepted they’ve become a standard. Ruby’s concept Gems on the other hand are baked right into the language.
You’ll soon seen how PHP’s Composer Packages are so similar, yet so different from Ruby Gems and it’s Bundler package manager.
Installing PHP Packages Globally
As you’ve probably done a few times, you’ll need to first install Composer onto your computer.
Once you have the
composer installed you’ll be able to use the
global flag to install packages. For this example we’ll install the Laravel Installer globally as if we were going to start a new Laravel project:
composer global require "laravel/installer"
Volia. We now have the
laravel executable availabe in our
$PATH which is just a fancy way of saying we can call
laravel from any directory we’re in.
Now we can create Laravel projects wherever we’d like:
laravel new example_laravel_project
Installing Gems Globally
Contrary to PHP, we do not need to install anything besides Ruby itself to get started downloading Gems to be used globally.
For this example we’ll download the gem to use the Rails framework. This is very similar to installing Laravel globally. But no need to install an external package manager for global packages:
gem install rails
That’s it. The
rails executable is now available globally in our Terminal:
rails new example_rails_project
Same results, 1 less step for the Ruby folks.
Installing Packages per Application in PHP
This is actually going to be a 2 parter. You will need to first create a
composer.json file. This file tells Composer the various settings, metadata and which packages are required in for the application.
First, we need to create a
composer.json file. Lucky for us we don’t need to Google around for “composer.json file template”, there’s a handy command baked into the
composer executable we downloaded earlier:
This will walk you through the various settings of your
- Package Name
- Minimum Stability
- Package Type
For this example you can just hit enter a bunch of times.
Now that we have a valid
composer.json file, you can start installing packages.
In addition to providing a command to installing packages globally, there is a command to installing packages onto the current application. Within the same directory as where we ran
composer init run:
composer require guzzlehttp/guzzle
This will install Guzzle which is an execellent PHP library for sending HTTP requests. I highly recommend it.
Assuming you’ve required the Autoloaded class generated by Composer and PSR-4 autoloaded your application’s files, you can now use GuzzleHttp throughout your project:
When we ran
composer require guzzlehttp/guzzle, Composer looked inside of the
composer.json file and added the latest Guzzle version in the
dependencies section of the file.
Then it downloaded the Guzzle package from the Packagist repository to the
vendor directory in your current directory.
Installing Gems per Application on Ruby
Much like PHP, Ruby needs a special file in the application’s directory to list the packages a.k.a. Gems that are required for the application to run properly.
We covered Composer’s
composer.json, but in Ruby it’s a
A Gemfile serves the same purpose as a
composer.json file. It lists some metadata about the author, liscense, etc. More importantly it lists the dependencies needed for the application to run.
One caveat about
Gemfile’s that are similar to Composer’s
composer.json - it’s not part of the language. We actually need to install a Gem to manage our Gems. Very recursive I know.
gem install bundler
This command will install Bundler as a global Gem on your computer. Bundler is in essence the same as Composer. It looks for a
Gemfile and downloads the list of Gems that are listed.
Now that we have Bundler installed, we can create a
Gemfile with the built in command:
bundle init => Writing new Gemfile to /home/pierce/projects/php_to_ruby/bundler_example
That’s it. It doesn’t ask us any questions like
composer init does.
If you open up the freshly created
Gemfile you should see something like this:
# frozen_string_literal: true source "https://rubygems.org" # gem "rails"
It’s not a JSON format like we’re used to, but you can probably guess if we’d uncomment the
# gem "rails" section, that would require Rails in our project. Let’s do just that.
Now your Gemfile should look like this:
# frozen_string_literal: true source "https://rubygems.org" gem "rails"
Once the file is saved, run
bundle install in the same directory as the
Gemfile. Soon you’ll see all of the Rails gem dependencies downloading on your Terminal screen in wild technicolor.
Congratulations, you just downloaded your first Gem through Bundle! It’s a big moment. With this skill you’ll be able to interact with the rich Ruby ecosystem and build your projects on the shoulders of giants, also with other awesome developers.
Where to Find Additional Gems
If you have your
Gemfile open, you can look near the top for the clue where the source of your Gems are:
Nice nice naming huh?
Adding more Gems to your Gemfile follows the same pattern - open your
Gemfile and add a new line that corresponds to the Gem you’d like to install.
I’m a huge fan of the RSpec Gem for testing my Ruby code so let’s visit their RubyGems page:
You’ll see a little text box noted “GEMFILE”, copy it’s contents. It should look a little something like this:
> gem 'rspec', '~> 3.7'
Now paste it inside of your
# frozen_string_literal: true source "https://rubygems.org" gem 'rails" gem 'rspec', '~> 3.7'
bundle install and soon you’ll have
rspec available to use in your Application.
Is there a “bundle require” command?
It’s the exact format as
composer require vendor/package-name but it’s very close. You can install Gems and have them automagically added to your Gemfile with:
bundle add rspec
This command will automatically add the package you pass to it to the local Gemfile and update your Gemfile.lock. Nifty!
Composer.lock & Gemfile.lock - What’s the difference?
The first time you run
composer install or
bundle install in a project, you’ll see a file get generated -
composer.lock for Composer and
Gemfile.lock for Bundle.
If you don’t already know, these files are responsible for locking the versions of packages and gems to the current version.
This way, if you or another developer downloads your project and runs
composer install or
bundle install, Composer or Bundler will look for for that
*.lock file first and download those packages.
This is why you should never run
composer update or
bundler update in production.
Essentially what you’re telling your dependency manager is “hey, grab the latest version of the package if I didn’t define it.” This could lead you to accidentally download a package that’s not backwards compatible and could break your application.
Keeping packages updated is important for 2 reasons:
- When security related bugs are found in packages, developers will fix the bug and upgrade the version of the package
- New features are added to packages all of the time, and sometimes you get performance boosts, bug fixes or new functionality you otherwise wouldn’t have
- Software is kind of like a long run. Whenever a framework or package with many dependencies has a major version change, all of the packages that support it and vice versa will eventually need to adapt. If you don’t take the time to keep up with the rest of the herd, you may find yourself paying for it later. We call this concept “Technical Debt”.
Lucky for us, it’s never been easier to keep up with package updates.
The command is identical across both languages: