Composer Packages

By the end of this lesson you'll manage third-party libraries with Composer, wire up PSR-4 autoloading so your classes load themselves, choose the right version constraints, and publish your own package to Packagist for the world to use.

Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.

Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

What You'll Learn in This Lesson

1️⃣ What Composer Is & the Four Commands

Composer is PHP's dependency manager — a tool that downloads the third-party libraries your project needs and keeps track of their versions. You almost never write a logging system, a date library, or an HTTP client yourself; you require a battle-tested one. There are four commands you'll use daily: composer init creates a new composer.json , composer require adds a package, composer install installs the exact versions a project already locked, and composer update upgrades to the newest versions your rules allow.

2️⃣ composer.json vs composer.lock

These two files trip up everyone at first, so make the distinction stick. composer.json is your wish list : it says which packages you want and the version ranges you'll accept. composer.lock is the receipt : Composer generates it automatically, recording the single exact version of every package — and every sub -dependency — it actually installed. Because the lock pins everything precisely, composer install reproduces the identical dependency tree on every machine.

3️⃣ PSR-4 Autoloading & vendor/autoload.php

In the old days you wrote a require for every single class file — tedious and fragile. PSR-4 is the modern standard that ends that: it maps a namespace prefix to a folder , so Composer can find a class file from its name alone. You declare the mapping once in composer.json , run composer dump-autoload , then require 'vendor/autoload.php' a single time. From then on, the first time you use a class, Composer loads the matching file for you. A sub-namespace simply means a sub-folder.

The magic is vendor/autoload.php — a file Composer writes for you. Including it registers an autoloader : a function PHP calls whenever you reference a class it hasn't loaded yet. It translates into src/Post.php and loads it on demand. If you add a new class and PHP says it can't find it, you usually just need to run composer dump-autoload to refresh the map.

4️⃣ Semantic Versioning & Constraints (^ vs ~)

Every package version is MAJOR.MINOR.PATCH — a patch is a bug fix, a minor adds features without breaking anything, and a major bump signals a breaking change. In composer.json you don't pin one fixed version; you give a constraint so you keep receiving safe fixes. The caret ^ is the common default — it allows everything up to the next major. The tilde ~ is stricter, usually allowing patch releases only.

5️⃣ Dev Dependencies & Scripts

Not every dependency ships to production. Tools like PHPUnit (testing) and PHPStan (static analysis) belong under require-dev — they're installed on your laptop and CI server but skipped on a production deploy with composer install --no-dev . You can also define scripts : named shortcuts for commands you run constantly, so a long incantation becomes a short composer test .

6️⃣ Your Turn: Install & Autoload

Now you try. The terminal session below is almost complete — fill in each ___ using the 👉 hint, then check it against the Output panel.

One more — this time PSR-4. The class is at src/Money/Price.php and the prefix maps to src/ . Give the class the matching namespace and load the autoloader.

📋 Quick Reference — Composer

No code is filled in this time — just a brief and an outline. Write it yourself, run the PHP part on onecompiler.com/php or your own machine, then check your result against the expected output in the comments. This mirrors how you'd actually scaffold a real package.

Practice quiz

Which Composer command adds a new dependency to your project?

  • composer install
  • composer update
  • composer require
  • composer dump-autoload

Answer: composer require. composer require downloads the package into vendor/, records it in composer.json, and pins the version in composer.lock.

What does composer.json hold?

  • Your wish list: the packages you want and the version ranges you'll accept
  • The exact pinned version of every package
  • The downloaded library code
  • Your database credentials

Answer: Your wish list: the packages you want and the version ranges you'll accept. composer.json is the wish list of ranges like ^3.7; composer.lock is the receipt of exact installed versions.

Which command installs the EXACT versions already pinned in composer.lock?

  • composer require
  • composer update
  • composer init
  • composer install

Answer: composer install. composer install reads the lock file so every machine installs identical versions. composer update re-resolves ranges and rewrites the lock.

Should you commit composer.lock for a deployed application?

  • No — let each machine resolve its own
  • Yes — so everyone installs byte-for-byte identical dependencies
  • Only on Fridays
  • Only if it's under 1 MB

Answer: Yes — so everyone installs byte-for-byte identical dependencies. Commit composer.lock for applications (reproducible builds). For a reusable library you publish, don't commit it. Never commit vendor/.

What does PSR-4 autoloading map?

  • A namespace prefix to a base folder
  • A function name to a file line
  • A package to a Packagist URL
  • A class to a database table

Answer: A namespace prefix to a base folder. PSR-4 maps a namespace prefix to a folder, e.g. Acme\Blog\ -> src/, so Acme\Blog\Post is found at src/Post.php.

Which single line do you include to load every Composer-managed class?

  • require 'composer.json';
  • use Composer\Autoloader;
  • require 'vendor/autoload.php';
  • include 'vendor/all.php';

Answer: require 'vendor/autoload.php';. Including vendor/autoload.php registers the autoloader; classes are then loaded on demand the first time you use them.

What does the caret constraint ^3.7.0 allow?

  • Exactly 3.7.0 only
  • >=3.7.0 and <4.0.0 (up to but not including the next major)
  • >=3.7.0 and <3.8.0 (patches only)
  • Any version at all

Answer: >=3.7.0 and <4.0.0 (up to but not including the next major). The caret ^ allows everything up to the next major — so 3.8, 3.9, 3.10 but never 4.0. It's the common default.

What does the tilde constraint ~3.7.0 allow?

  • >=3.7.0 and <4.0.0
  • Exactly 3.7.0
  • Any 3.x or 4.x version
  • >=3.7.0 and <3.8.0 (patch releases only)

Answer: >=3.7.0 and <3.8.0 (patch releases only). ~3.7.0 (three parts) allows patches only: 3.7.1, 3.7.2 ... It's stricter than the caret.

Where do development-only tools like PHPUnit belong?

  • Under require
  • Under require-dev
  • In composer.lock manually
  • In the vendor/ folder you commit

Answer: Under require-dev. require-dev holds test/lint tools; they're skipped in production with composer install --no-dev.

How do you publish your own package so others can require it?

  • Email the zip to Composer
  • Run composer publish
  • Tag a git version (e.g. v1.0.0), push tags, and submit the repo URL to Packagist
  • Commit vendor/ to GitHub

Answer: Tag a git version (e.g. v1.0.0), push tags, and submit the repo URL to Packagist. Composer reads git tags as versions; you submit the repo URL at packagist.org and enable the webhook so new tags publish automatically.