Skip to content

Instantly share code, notes, and snippets.

@jpcercal
Created April 26, 2017 21:30
Show Gist options
  • Save jpcercal/a5c8b86f2153bd8ff5c8bc56306386a9 to your computer and use it in GitHub Desktop.
Save jpcercal/a5c8b86f2153bd8ff5c8bc56306386a9 to your computer and use it in GitHub Desktop.
Article

How do you get your environment variables using PHP?

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.

A real application

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.

But, what is rclone?

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.

How can I install rclone on my machine

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.

How to configure rclone

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.

Creating our PHP project

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. =)

Dependency Manager

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.

Creating our Environment Variables

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

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);
            }
        });
    }
}

How can I run this command line application?

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".

Conclusion

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";

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment