PHP Steem Apps with Steem Connect and Laravel - Part II: Steem Configuration and Service Provider

in #utopian-io7 years ago (edited)

image.png

What Will I Learn?

This tutorial is the second installment of a series of tutorials providing step-by-step instructions to bootstrap a Steem based application using the Laravel Framework and SteemConnect (though the SteemConnect SDK for PHP).

  • 1 - Steem Configuration File.
  • 2 - Configuration Variables (.env file).
  • 3 - Service Providers.

Requirements

To follow this tutorial series, you should be familiar with the following:

  • Followed the previous installments of this tutorial series.
  • A PHP 7.1+ environment with Composer installed.
  • Basic PHP experience.
  • Basic Laravel Framework experience.
  • Basic understanding of SteemConnect.
  • Basic understanding of the Steem blockchain RPC.
  • Basic command line experience.

Difficulty

  • Basic to Intermediate, depending on the previous knowledge of each of the requirements.

Tutorial Contents

On the last installment, we created a Laravel application, set it's namespace, and installed both SteemConnect SDK for PHP and LightRPC as dependencies.

Now, we are going to configure each one of those to use within Laravel. Also, we are going to create the respective Service Provider that will allow easy usage within a Laravel application.

Steem Configuration File.

Everything we need to configure the application will be stored on a special configuration file for Steem related variables. We will call this file config/steem.php

Instead of building each piece of this file, let's just create the whole file at once, and from that, we can cover each section and why it matters.

So, create the config/steem.php with the following content:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Application settings
    |--------------------------------------------------------------------------
    |
    | Basic Steem application name, version and community settings.
    |
    */
    'app' => [
        // application name.
        'name' => env('STEEM_APP_NAME', 'blocker.press'),

        // application version.
        'version' => env('STEEM_APP_VERSION', '1.0'),

        // application community name.
        'community' => env('STEEM_COMMUNITY', null),
    ],

    /*
    |--------------------------------------------------------------------------
    | Steem RPC URL
    |--------------------------------------------------------------------------
    |
    | HTTPS steem RPC URL.
    |
    */

    'rcp' =>  [
        'url' => env('STEEM_RPC_URL', 'https://api.steemit.com'),
    ],

    /*
    |--------------------------------------------------------------------------
    | Steem Connect Configuration
    |--------------------------------------------------------------------------
    |
    | OAuth SteemConnect SDK client configuration.
    |
    */

    'sc2' => [
        // OAuth client ID.
        'client_id' => env('STEEM_SC2_ID', null),
        // OAuth client secret.
        'client_secret' => env('STEEM_SC2_SECRET', null),

        // OAuth scopes. Scopes should be comma delimited.
        'scopes' => env('STEEM_SC2_SCOP', 'login,comment'),

        // OAuth return URL.
        'return_url' => env('STEEM_SC2_RETURN_URL', 'http://localhost:8080/auth/callback'),
    ],
];

Notice that on that file, we use the env() function on all configuration keys. That allows us to set some fallback, default values, but mainly, it sets a environment variable name that can be customized on the .env file, which we will update on the next section of this tutorial.

For now, let's just cover what the configuration file is about.

First, let's cover the 3 main keys on the configuration file:

  • 'app'

The 'app' key covers the application name, version and community. The name and version, together are used to build an application internal name, that can be used by other Steem applications to indicate what application was used by the author to post on Steem.

One example: dtube/0.9 covers the application as DTube and indicates the DTube version 0.9 was used to post.

On the other side, community is commonly used by many Steem applications, but I don't recollect it being used by other applications. Let's be compliant and set that piece anyway.

  • 'rpc'

The RPC key on the configuration file, covers which RPC node will be used to retrieve content from the Steem blockchain, it defaults to Steemit public RPC node.

This information will be later used by LightRPC client, which supports only HTTPS calls to RPC nodes.

  • 'sc2'

On the 'sc2' configuration key, we configure the credentials for calling SteemConnect.

Notice that, the values of client_id and client_secret keys, are the same ones we obtained on the SteemConnect dashboard while creating the application, on the Part I of this tutorial.

The scopes (under the scopes key ) are a comma delimited list of OAuth scopes our application will ask the users for.

A complete list of scopes and their respective descriptions is available on the SteemConnect SDK for PHP docummentation. Chose the ones your application will need.

If you are confuse about the scopes, I do recommend you read more about on the previously mentioned documentation, it will give You a better idea of what they mean.

Lastly, we have the return_url key, which is basically the URL we previously set on the SteemConnect dashboard while creating the application, remember? Both application and SteemConnect values for return URL must match, or you will end up with an error.

Configuration Variables (.env file).

As mentioned on the previous section, all values under the configuration file references environment variables, and their respective default values can customized on the .env file

Now, we can append the new environment variables into the .env file:

STEEM_APP_NAME=larasteem
STEEM_APP_VERSION=1.0
STEEM_COMMUNITY=LaraSteem

STEEM_RPC_URL=https://api.steemit.com

STEEM_SC2_ID=larasteem.app
STEEM_SC2_SECRET=the-secret-from-steemconnect-dashboard-here
STEEM_SC2_SCOPES=login,vote,comment,offline,custom_json
STEEM_SC2_RETURN_URL=http://localhost:8080/auth/callback

Notice, We are customizing the id, secret and scopes on the .env file, any change on the .env file will override the configuration file default values, and that is exactly what we wanted.

Now, as decent human beings, we may update the .env.example file as well, to help other developers that may work on the application with a starting point for the environment variables. Just be sure to remove sensitive information from the .env.example file.

Service Provider

Service Providers are a powerful feature of the Laravel framework. On this section we will leverage this functionality to register both SteemConnect SDK and LightRPC client using a Service Provider.

The Service Provider will register the instances of both SteemConnect and LightRPC under the Inversion-of-Control (IoC) container, which will make the usage of both libraries easy from any context, including controller auto injection.

To start a controller, use Artisan, by issuing the following command:

php artisan make:provider SteemProvider

This commend will generate a stub Provider at lara-steem/app/Providers/SteemProvider.php.

This provider, while empty, will be now updated to instantiate and register the components under the IoC container.

One quick thing before we continue here: Both SteemConnect and LightRPC libraries name it's Client classes as Client, to solve the naming conflict, we will right away, import those classes with the use declaration of PHP.

On the top of SteemProvider class, include the two client classes as following:

use Illuminate\Support\ServiceProvider;
use SteemConnect\Client\Client;
use LightRPC\Client as LightRPC;

Notice, we are aliasing the LightRPC Client class as LightRPC, so we don't have a naming conflict.

Also, let's speed up things and include another class that will be required, the SteemConnect SDK Config class.

The start of the Service Provider should now look like this:

<?php

namespace LaraSteem\Providers;

use Illuminate\Support\ServiceProvider;
use LightRPC\Client as LightRPC;
use SteemConnect\Client\Client;
use SteemConnect\Config\Config;

...

Also, notice that I've sorted the imported alphabetically, it has no effect on the final code, but for sure, it's a good pratice.

Now, we can move ahead, and create a configuration instance, let's dedicate a method for it, and call this method factoryConfig(). This method should be responsible for bootstraping a configuration object for the SteemConnect SDK, using the values from configuration we previously set on this tutorial.

Inside this method, let's first get the required variables for the Config instance, then create the Config instance itself:

// get client id and secret from config.
$clientId = config('steem.sc2.client_id');
$clientSecret = config('steem.sc2.client_secret');
        
// creates a new SteemConnect configuration instance.
$config = new Config($clientId, $clientSecret);

After creating the bare instance, we can configure the OAuth part of it: The return URL and the required scopes:

For the scopes, since the Client wants an array of scopes, and we defined those same scopes on the configuration as a comma separated string of values, we must explode (make each value delimited by a comma into an array item.)

// get all scopes and explode into an array.
$scopes = explode(',', config('steem.sc2.scopes'));
// set the scopes on the configuration instance.
$config->setScopes($scopes);

Also, we need to set the return URL, that one we configured on the SteemConnect application, and agreed being http://localhost:8080/auth/callback for the time being.

// get the return URL from config.
$returnUrl = config('steem.sc2.return_url');
// set the return URL on the config instance.
$config->setReturnUrl($returnUrl);

Now, we can also set the last bits. Remember the community on our configuration defaulted to null? Since it may not be present, we must check first for it's value, and only set it on config then.

// get the community name.
$community = config('steem.app.community');
        
// set the community, if one was set.
if ($community) {
    $config->setCommunity($community);
}

And now, the application name, which consists of a application slug, a slash and a version:

// build an application name / version string.
$appName = config('steem.app.name')."/".config('steem.app.version');
// set the application name on the config instance.
$config->setApp($appName);

Finally, we can return the config object:

// return the config.
return $config;

Just to ensure we did all correctly on this section, here is what this method should looks like after following the example:

/**
 * Generate a SteemConnect Config instance.
 *
 * @return Config
 */
protected function generateConfig() : Config
{
    // get client id and secret from config.
    $clientId = config('steem.sc2.client_id');
    $clientSecret = config('steem.sc2.client_secret');

    // creates a new SteemConnect configuration instance.
    $config = new Config($clientId, $clientSecret);

    // get all scopes and explode into an array.
    $scopes = explode(',', config('steem.sc2.scopes'));
    // set the scopes on the configuration instance.
    $config->setScopes($scopes);

    // get the return URL from config.
    $returnUrl = config('steem.sc2.return_url');
    // set the return URL on the config instance.
    $config->setReturnUrl($returnUrl);

    // get the community name.
    $community = config('steem.app.community');

    // set the community if one was set.
    if ($community) {
        $config->setCommunity($community);
    }

    // build an application name / version string.
    $appName = config('steem.app.name')."/".config('steem.app.version');
    // set the application name on the config instance.
    $config->setApp($appName);

    // return the config.
    return $config;
}

Now, we can actually register the the SteemConnect SDK Client. Let's create another protected method, called registerSteemConnect():

/**
 * Register the SteemConnect client on the IoC.
 */
protected function registerSteemConnect()
{
    // register the SteemConnect 2 client under a string alias.
    $this->app->singleton('sc2.client', function () {
        // get the config instance.
        $config = $this->generateConfig();
        // create and return the SteemConnect client instance.
        return new Client($config);
    });
    
    // register the client class itself with the same instance
    $this->app->singleton(Client::class, function () {
        // return the previous instance from IoC.
        return $this->app->make('sc2.client');
    });
}

If you got lost, first, we created a SteemConnect instance, using the Config instance generated from the previously created method, and assigned this instance under the sc2.client key on the Laravel IoC container.

After, we repeated the process, aliasing the Client class name with a single instance. This step will prevent us from creating multiple instances of the Client over and over on the application's code.

Now, it's time to repeated the process, but for the LightRPC client, which we previously aliased as LightRPC:

/**
 * Register the LightPRC client on the IoC.
 */
protected function registerLightRPC()
{
    // register the LightRPC client under a string alias.
    $this->app->singleton('light-rpc.client', function () {
        // get the API url.
        $apiUrl = config('steem.rpc.url');
        // create and return a LightRPC instance.
        return new LightRPC($apiUrl);
    });
    
    // register the class itself with the same instance.
    $this->app->singleton(LightRPC::class, function () {
        // return the previous instance from IoC.
        return $this->app->make('light-rpc.client');
    });
}

The process was the same indeed, we registered under two different names, one for quick reference (light-rpc.client and sc2.client) and another, the full class name, for dependency injection later on the controllers.

Now, we can update the register() method on the provider, to call the two recently created methods:

/**
 * Register services.
 *
 * @return void
 */
public function register()
{
    // register SteemConnect.
    $this->registerSteemConnect();
    // register LightRPC.
    $this->registerLightRPC();
}

In order to prevent repeating myself, if for some reason you wanna check the whole file resulting from the tutorial, do so on the Github repository.

Our provider is complete, and ready to be enabled on the application!

Update the config/app.php, under the 'providers' key, appending the recently created provider at the end:

'providers' => [
    // other providers omited...
    
    LaraSteem\Providers\SteemProvider::class
],

Curriculum

You just read the Part II of a tutorial series, all installments are listed bellow:



Posted on Utopian.io - Rewarding Open Source Contributors

Sort:  
  • as this tutorial is about the installment , it would be more appreciated if you merge your first one and this one as one full tutorial for teaching how to install the application.
  • since i have approved your last one , you could add this part content into your last one post as the whole first part of the tutorials

Need help? Write a ticket on https://support.utopian.io.
Chat with us on Discord.

[utopian-moderator]

Got it. I'll add this one to the first and start the next content as the second one. thanks.

@cha0s0000, I have instead, included the next topic under this same tutorial, even if the rejection could not be reversed, I thought it made more sense from the content perspective, making the next part (III) start on the development itself, and not on any configuration.

Thank you!