PHP: Installing and Using Composer
How to install and use composer locally, without the need to write sudo all the time.
By. Jacob
Edited: 2020-06-26 10:38
Before we can use composer to install things we need in PHP projects, we will need to download and run the setup file. To do this, it is recommended to follow the official instructions on this page:
https://getcomposer.org/download/
The setup file composer-setup.php makes sure your php.ini is configured correctly, and alerts you if not.
It also downloads a file, composer.phar, which should be moved to ~/.local/bin.
While moving the .phar file, we also rename it to composer, since the extension is not needed.
mv composer.phar ~/.local/bin/composer
Placing composer in this location allows us to use composer without having to use sudo, which is very convenient.
Note. The ~/.local/bin/ location can also be used for your own custom scripts and binaries.
Installing things with composer
Now, to install something, we can navigate to the project directory to make it easier; if you are using a typical Apache virtual host (vhost) setup this can probably be done by typing something like:
cd /var/www/MyProjectName/
Within the project root, we can now try to install PHPMailer (without sudo):
composer require phpmailer/phpmailer
This will create the vendor directory in the root of your project; the vendor directory will contain all the dependencies, such as PHPMailer, that are installed with composer.
Using the autoloader, we can then use the dependency we just installed like this:
// index.php
// Composition Root
//
define('BASE_PATH', rtrim(preg_replace('#[/\\\\]{1}#', '/', realpath(dirname(__FILE__))), '/') . '/');
require BASE_PATH . 'vendor/autoload.php';
// PHPMailer Object
$mail = new PHPMailer\PHPMailer\PHPMailer();
$mail->addAddress("[email protected]", "FirstName LastName");
// ...
Using the autoloader to include dependencies from vendors
Possibly due to autdated documentation, the install process is not always smooth. Dependencies are installed as [Vendor Name] / [Project Name]; and in the case of PHPMailer, this becomes PHPMailer/PHPMailer—this is important to keep in mind, since it refers to the namespace that we need when auto-loading.
I am not sure why we can not just write new PHPMailer()..., as mentioned in some tutorials. Presumably, the composer autoloader should be able to automatically handle namespaces, but that does not appear to be the case.
Instead, we have to include the dependency by writing the full namespace:
$mail = new PHPMailer\PHPMailer\PHPMailer();
This is unnecessarily complicated, and it just looks weird. Instead of doing that, we can also rely on use statements in the top of our composition root (I.e: index.php):
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer();
This is still somewhat of an inconvenience, but at least we can then make a separate file with use statements, and then just include it where needed.
Another problem is that it can be hard to know the exact namespace/path of a given dependency since documentation is so poor, and I have not found an easy solution to that. Right now you will probably look at the file itself to determine what you need to write to include it.
Remember: the purpose of autoloading is to avoid having to write all those require and include statements; most often we still need to write out the namespace.
The confusion likely comes from back when dependencies were in the global namespace. But, that is just a guess on my part, since I have not used composer much until now.
Feel free to comment if you have information on this, and I will update the article ASAP.
Tell us what you think: