You probably get your environment variables using built-in PHP functions such as getenv
or $_ENV
, but did you know that you can do it in an elegant way getting the value of an environment variable in the properly PHP data type with the powerful library? If you are curious, just read how this energetic library can help you in your daily development workflow.
Note that in this article we'll use a famous library to load environment variables from an external file, this library is vlucas/phpdotenv
.
Then, firstly, you need to install the dependencies. To do it, simply type this in your terminal:
$ composer require vlucas/phpdotenv
$ composer require cekurte/environment
Now, we need to create a .env
file and put the first env var in it.
$ touch .env
$ echo "PHP_DEBUG=true" > .env
Let's read the environment variable and dump his value to the screen.
<?php
require 'vendor/autoload.php';
use Cekurte\Environment\Environment;
use Dotenv\Dotenv;
$dotenv = new Dotenv(DIR);
$dotenv->load();
var_dump(Environment::get("PHP_DEBUG"));
// If you run this code, you'll see like a magic:
// bool(true)
Did you see that the data type of this value is a bool and not a string? Cool, but it could be better.
Let's move on to the next step and explore more features, what do you think in save your configurations in a unique environment variable as an array? That's sounds good, at least for some occasions:
$ echo "NUMBERS=[0,2,4,6,8]" >> .env
<?php
// ... more code here
var_dump(Environment::get("NUMBERS"));
// array(5) {
// [0]=> int(0)
// [1]=> int(2)
// [2]=> int(4)
// [3]=> int(6)
// [4]=> int(8)
// }
Good one. Did you see that you can define complex data structures to your env vars?
Note: If you want, you can read the documentation of cekurte/environment
to understand how many data types you can use there with examples trying to explain how to do it and what is supported by this library.
In the next section, we will code a real application that uses the same concept shown below to get configurations and we will do it creating a wrapper to rclone
.
Well, we will use rclone to connect on Amazon Cloud Drive and list every file from there in a specific folder. Feel free to implement wherever you want if this idea, like for example upload your files to your Amazon Cloud Drive, files like database backups maybe, just relax and use your imagination.
Rclone is command line program that can be used to synchronize the files from a source to a target. Actually it supports some providers like:
- Google Drive
- Amazon S3
- Dropbox
- Google Cloud Storage
- Amazon Drive
- Microsoft OneDrive
- SFTP
- The local filesystem
To see the complete list of supported providers, please read more on rclone's homepage.
To install this tool, you can follow the official documentation that will explain how to install it on your machine (it works on Windows, Linux and OSX, so don't worry), maybe you are thinking different and you want to install it on your server, yes you can do it without any problems.
You will need to configure rclone to any cloud providers that you want to use with it, so, in that case we will just configure the Amazon Cloud Drive account.
Before move on, be sure that you have rclone on your PATH operating system variable and run the following command to configure rclone to manage files of our cloud drive.
$ rclone config
Note: you will be asked about an alias, as a convention to this tutorial I'm supposing the we are using the alias amazon
and you have a specific folder in the root directory named CodeShip
.
Fill the information according to the questions, and after that when you run this command you will see all files of your cloud root folder:
# rclone ls your-alias:/
rclone ls amazon:/CodeShip
This command will print to the console every file that are there on CodeShip folder of your Amazon Cloud Drive.
If it's working, let's move on.
We will follow few steps to get our application working, so just following the step-by-step guide to create and run or application, if you have any doubt about the any steps, please leaves us a comment to discuss it in more details, or send me a message directly. I'll love talk with you about it. =)
Composer is the dependency manager tool that we will use, this is the start point. Let’s create a new PHP project and import a few dependencies using composer.
Note: when you enter the first command composer init
you will be asked about the configurations of your new project.
$ composer init
$ composer require vlucas/phpdotenv
$ composer require cekurte/environment
$ composer require symfony/process
$ composer require symfony/console
There is more one thing to finish the composer configuration, we need to say what is the namespace of our application. To do it, you need to add an autoload
field to composer.json
file like this:
{
"autoload": {
"psr-4": {"App\\": "src/"}
}
}
Composer will register a PSR-4 autoloader for the App
namespace.
Our environment variables will keep the configurations of our command line application, here is the point where you can change the path to rclone
binary for example, or change the configuration of your anything that you are seeing above.
Let's create the enviroment variables file .env
in the root folder of our project and fill it with some useful configs to the scope of this application.
$ touch .env
$ echo "CLOUD_PROVIDER={'alias': 'amazon', 'directory': '/CodeShip'}" > .env
$ echo "RCLONE_BIN=/usr/bin/rclone" >> .env
$ echo "RCLONE_DEFAULT_ARGS=['--verbose']" >> .env
That's it, the CLOUD_PROVIDER
has a json
content and it will be used to retrieve the information about your specific configuration that we did in rclone config
.
The RCLONE_BIN
has a string
that will point to the binary installation path of rclone
tool on your machine
And, the RCLONE_DEFAULT_ARGS
has an array
that will be used to send rclone commands with this default arguments.
The ListCommand
will be the class responsible to list all files that are inside of our CodeShip
folder on Amazon Cloud Drive.
Well, firstly create the src
directory in your project folder and inside of it create the ListCommand.php
file.
$ mkdir src
$ touch src/ListCommand.php
The content of ListCommand.php
will be:
<?php
namespace App;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\ProcessBuilder;
class ListCommand extends Command
{
protected function configure()
{
$this
->setName('app:list')
->setDescription('List the content of your remote folder.')
->setHelp('This command will list every file that´s inside of your cloud drive folder.')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$io = new SymfonyStyle($input, $output);
$cloudProvider = Environment::get('CLOUD_PROVIDER');
$io->section(sprintf(
'Listing files from "%s:%s".',
$cloudProvider['alias'],
$cloudProvider['directory']
));
$builder = new ProcessBuilder();
$builder->setPrefix(sprintf(
"%s ls %s:%s",
Environment::get('RCLONE_BIN'),
$cloudProvider['alias'],
$cloudProvider['directory']
));
$process = $builder
->setArguments(Environment::get('RCLONE_DEFAULT_PARAMS'))
->getProcess()
->setTimeout(3600)
->setIdleTimeout(60)
;
$process->start();
$process->wait(function ($type, $buffer) use ($io) {
if (Process::ERR === $type) {
$io->error($buffer);
} else {
$io->text($buffer);
}
});
}
}
The last thing that we need to do is create a entry point file (our main
function).
$ touch app.php
Fill this file with the following content:
#!/usr/bin/env php
<?php
require 'vendor/autoload.php';
use App\ListCommand;
use Dotenv\Dotenv;
use Symfony\Component\Console\Application;
$dotenv = new Dotenv(dirname(__FILE__));
$dotenv->load();
$application = new Application();
$application->setName('RClone Wrapper');
$application->setVersion('v1.0');
$application->add(new ListCommand());
$application->run();
To run this application, just type it on your terminal:
php app.php
If you have any files on the folder CodeShip
in your amazon cloud drive, hence, those files will be listed on your console it's the expected behaviour.
Yes, I know it's really simple, but I just wanted to teach you about how you can use env vars in your project and why not think about complex data values in it, because "It´s not a bug, it's a feature".
As you can see, we can use environment variables to do a lot of things. You can increase the quality of your work just putting the configuration on environment variables to change the behaviour of a component in your application flow without change even a line of your source code.
It's really interesting and you don't need to convert your types, you just want to use the feature of a library to improve your performance and make your code easier to read and understand.
Let me know, if you have problems to follow this step-by-step tutorial and how or when you are thinking to use this feature on your next project.
Note that: the unique restriction that I can see about using environment variables is to set your database/api credentials for example, so take care about it.
Thank you very much for your time return "See you! =D";