How to filter out letters from text file (start of string and end) , then print them out

The function needs to skip the lines in text file (after reading it) with contains symbol or numbers in FIRST &amp;&amp; LAST string position. For example string($password column)&nbsp;<strong>1</strong>21dafas<strong>d</strong>&nbsp;should be skipped AND not printed out, because it starts with number I have tried many things, but all trials failed. Im new to PHP language

The function needs to skip the lines in text file (after reading it) with contains symbol or numbers in FIRST && LAST string position. For example string($password column) 121dafasd should be skipped AND not printed out, because it starts with number I have tried many things, but all trials failed. Im new to PHP language

THE CODE
 function dataPrint(){

print "\t"." Users: Login Password <br>";
$file=fopen("data.txt" , "c");
if (!$file)
print "Error! No such file!";

else {
print "<table><tr><th width="50%">Login</th>
<th width="50%">Password</th>
";
$info=file("data.txt");
foreach($info as $rec)
{

             $rec=rtrim($rec);

             print("&lt;tr&gt;");
             list($login, $pass) = explode(' ', "$rec");
             print("&lt;td&gt;$login&lt;/td&gt;");
             print("&lt;td&gt;$pass&lt;/td&gt;");

     }

print("</table>");

Right now it prints all data as table

Login   Password
quartz 2sp1lzod54at3sia6
quartz1 73u168rtz54a2q
quartz2 [email protected]

But it should print only those lines with contains only letters in start && end of string

Example :
Login Password
quartz1 [email protected] <----- NOT VALID(Should not be printed)
quartz2 asdf!2adf1 <----- NOT VALID(Should not be printed)
quartz3 [email protected] <----- VALID
quartz4 gsasdff11e <----- VALID
quartz5 [email protected]!adf1d <----- VALID

The end should look like this..

Login     Password
quartz3 [email protected]
quartz4 gsasdff11e
quartz5 [email protected]!adf1d


Developing RESTful APIs with Lumen (A PHP Micro-framework)

Developing RESTful APIs with Lumen (A PHP Micro-framework)

In this tutorial, I’ll show you how easy it is to build and secure an API with Lumen. Lumen is a PHP micro-framework built to deliver micro-services and blazing fast APIs. Learn how to build and secure RESTful APIs with Lumen

In this tutorial, I’ll show you how easy it is to build and secure an API with Lumen. Lumen is a PHP micro-framework built to deliver micro-services and blazing fast APIs. Learn how to build and secure RESTful APIs with Lumen

Lumen is an open-source PHP based micro-framework created by Taylor Otwell in 2015. Lumen is designed for building lightning fast micro-services and APIs. And it opts for maximum speed rather than flexibility in the bootstrapping process. The PHP micro-framework was born out of the need to have light Laravel installations that could be faster than existing PHP micro-frameworks such as Slim and Silex.

Lumen Features And Architecture

Lumen utilizes the Illuminate components that power the Laravel framework. One amazing thing about the way Lumen was built is the fact that you can painlessly upgrade right into Laravel. One of such scenarios where an upgrade process is applicable is when you discover that you need more features out of the box that Lumen doesn’t offer.

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

The entire bootstrap process is located in a single file.

Lumen Key Requirements

In order to use Lumen, you need to have the following tools installed on your machine.

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

Note: You’ll need MySQL for this tutorial. Navigate to the mysql website and install the community server edition. If you are using a Mac, I’ll recommend following these instructions. To avoid micromanaging from the terminal, I’ll also recommend installing a MySQL GUI, Sequel Pro.## Building a Fast Authors API Rapidly With Lumen

At Auth0, we have a number of technical writers, otherwise known as authors. A directive has been given to developing an app to manage Auth0 authors. The frontend app will be built with ReactJS. However, it needs to pull data from a source and also push to it. Yes, we need an API!

This is what we need the API to do:

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

Let’s flesh out the possible endpoints for this API. Given some authors resource, we’ll have the following endpoints:

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

What will be the author attributes? Let’s flesh it out like we did the endpoints.

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

Install Lumen

Run the following command in your terminal to create a new project with Lumen:

composer create-project --prefer-dist laravel/lumen authors


cd into the newly created project.

cd authors


Now, run php -S localhost:8000 -t public to serve the project. Head over to your browser. You should see the index page like so:

Authors Index

Activate Eloquent and Facades

As I mentioned earlier, the entire bootstrap process is located in a single file. Open up the bootstrap/app.php and uncomment this line, // app->withEloquent. Once uncommented, Lumen hooks the Eloquent ORM with your database as configured in the .env file.

Note: You’ll need MySQL for this tutorial. Navigate to the mysql website and install the community server edition. If you are using a Mac, I’ll recommend following these instructions. To avoid micromanaging from the terminal, I’ll also recommend installing a MySQL GUI, Sequel Pro.
In addition uncomment this line //$app->withFacades(); . Once uncommented, we can make use of Facades in our project.

Setup Database, Models and Migrations

At the time of this writing, Lumen supports four database systems: MySQL, Postgres, SQLite, and SQL Server. We are making use of MySQL in this tutorial. First, we’ll create a migration for the Authors table.

Note: You’ll need MySQL for this tutorial. Navigate to the mysql website and install the community server edition. If you are using a Mac, I’ll recommend following these instructions. To avoid micromanaging from the terminal, I’ll also recommend installing a MySQL GUI, Sequel Pro.
Run the command below in the terminal to create the Authors table migration:

php artisan make:migration create_authors_table


The new migration will be placed in your database/migrations directory. Each migration file name contains a timestamp which allows Lumen to determine the order of the migrations. Next, we’ll modify the recently created migration to accommodate the Authors attributes.

Open up the migration file and modify it like so:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAuthorsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('authors', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email');
            $table->string('github');
            $table->string('twitter');
            $table->string('location');
            $table->string('latest_article_published');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('authors');
    }
}


In the code above, we added the columns to the authors table.

Now, go ahead and run the migration like so:

php artisan migrate


Check your database. You should have the authors and migrations table present.

Let’s create the Author model. Create an app/Author.php file and add the code below to it:

app/Author.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'github', 'twitter', 'location', 'latest_article_published'
    ];

    /**
     * The attributes excluded from the model's JSON form.
     *
     * @var array
     */
    protected $hidden = [];
}


In the code above, we made the author attributes mass assignable.

Set up Routes

Routing is straight-forward. Open up routes/web.php and modify it like so:

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/

$router->get('/', function () use ($router) {
    return $router->app->version();
});

$router->group(['prefix' => 'api'], function () use ($router) {
  $router->get('authors',  ['uses' => '[email protected]']);

  $router->get('authors/{id}', ['uses' => '[email protected]']);

  $router->post('authors', ['uses' => '[email protected]']);

  $router->delete('authors/{id}', ['uses' => '[email protected]']);

  $router->put('authors/{id}', ['uses' => '[email protected]']);
});


In the code above, we have abstracted the functionality for each route into a controller, AuthorController. Route groups allow you to share route attributes, such as middleware or namespaces, across a large number of routes without needing to define those attributes on each individual route. Therefore, every route will have a prefix of /api. Next, let’s create the Author Controller.

Set up Author Controller

Create a new file, AuthorController.php in app/Http/Controllers directory and add the following code to it like so:

<?php

namespace App\Http\Controllers;

use App\Author;
use Illuminate\Http\Request;

class AuthorController extends Controller
{

    public function showAllAuthors()
    {
        return response()->json(Author::all());
    }

    public function showOneAuthor($id)
    {
        return response()->json(Author::find($id));
    }

    public function create(Request $request)
    {
        $author = Author::create($request->all());

        return response()->json($author, 201);
    }

    public function update($id, Request $request)
    {
        $author = Author::findOrFail($id);
        $author->update($request->all());

        return response()->json($author, 200);
    }

    public function delete($id)
    {
        Author::findOrFail($id)->delete();
        return response('Deleted Successfully', 200);
    }
}


Let’s analyze the code above. First, we required the Author model, use App\Author. Moving forward, we invoked the necessary methods from the Author model for each controller method. We have five methods here. showAllAuthors, showOneAuthor, create, update and delete.

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

For example, if you make a POST request to /api/authors API endpoint, the create function will be invoked.

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

Finally, test the API routes with Postman.

Author GET operation

Author POST operation

Author PUT operation

Author DELETE operation

Our API works. Awesome!

Lumen API Validation

When developing applications, never trust the user. Always validate incoming data. In Lumen, it’s very easy to validate your application’s incoming data. Lumen provides access to the $this->validate helper method from within Route closures.

Open up the AuthorController file and add modify the create method like so:

...
 public function create(Request $request)
    {
        $this->validate($request, [
            'name' => 'required',
            'email' => 'required|email|unique:users',
            'location' => 'required|alpha'
        ]);

        $author = Author::create($request->all());

        return response()->json($author, 201);
    }
...


Test the API POST route with Postman.

It validated the incoming requests and returned the appropriate error message.

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

Note: You’ll need MySQL for this tutorial. Navigate to the mysql website and install the community server edition. If you are using a Mac, I’ll recommend following these instructions. To avoid micromanaging from the terminal, I’ll also recommend installing a MySQL GUI, Sequel Pro.
Check out a plethora of validation rules that you can use with Lumen.

Securing the Authors API with Auth0

Right now, anyone can make GET and POST requests to all of the endpoints present in our API. In a real-world scenario, we should restrict POST, DELETE and PUT requests to certain registered and authorized users.

We’ll go ahead and secure some of these API endpoints with JSON Web Tokens.

JSON Web Tokens, commonly known as JWTs, are tokens that are used to authenticate users on applications. This technology has gained popularity over the past few years because it enables backends to accept requests simply by validating the contents of these JWTs. That is, applications that use JWTs no longer have to hold cookies or other session data about their users. This characteristic facilitates scalability while keeping applications secure.

Whenever the user wants to access a protected route or resource (an endpoint), the user agent must send the JWT, usually in the Authorization header using the Bearer schema, along with the request.

When the API receives a request with a JWT, the first thing it does is to validate the token. This consists of a series of steps, and if any of these fails then, the request must be rejected. The following list shows the validation steps needed:

  • Routing: Lumen provides routing out of the box via Fast Route. Fast Route is a library that provides a fast implementation of a regular expression based router.
  • Authentication: Lumen does not support session state. However, incoming requests are authenticated via a stateless mechanism such as tokens.
  • Caching: Lumen supports caching just like Laravel. In fact, there are no differences between using the cache in Lumen and Laravel. Cache drivers such as Database, Memcached, and Redis are supported. You will need to install the illuminate/redis package via Composer before using a Redis cache with Lumen.
  • Errors and Logging: Lumen ships with the Monolog library, which provides support for various log handlers.
  • Queuing: Lumen provides a queuing service that is similar to Laravel’s. It provides a unified API across a variety of different queue back-ends.
  • Events: Lumen’s events provide a simple observer implementation, allowing you to subscribe and listen for events in your application.

We will make use of Auth0 to issue our JSON Web Tokens. With Auth0, we have to write just a few lines of code to get a solid identity management solution, including single sign-on, user management, support for social identity providers (like Facebook, GitHub, Twitter, etc.), enterprise (Active Directory, LDAP, SAML, etc.), and your own database of users.

For starters, if you haven’t done so yet, this is a good time to sign up for a free Auth0 account. Having an Auth0 account, the first thing that we must do is to create a new API on the dashboard. An API is an entity that represents an external resource, capable of accepting and responding to protected resource requests made by clients.

Note: You’ll need MySQL for this tutorial. Navigate to the mysql website and install the community server edition. If you are using a Mac, I’ll recommend following these instructions. To avoid micromanaging from the terminal, I’ll also recommend installing a MySQL GUI, Sequel Pro.
Login to your Auth0 management dashboard and create a new API client.

Click on the APIs menu item and then the Create API button. You will need to give your API a name and an identifier. The name can be anything you choose, so make it as descriptive as you want.

The identifier will be used to identify your API, this field cannot be changed once set. For our example, I’ll name the API, Authors API, and for the identifier, I’ll set it as https://authorsapi.com. We’ll leave the signing algorithm as RS256 and click on the Create API button.

Create a New API

Creating the Authors API

You can define scopes in this section

Head over to your terminal and install Auth0 PHP SDK:

composer require auth0/auth0-php:~5.0


Create a new middleware file, Auth0Middleware.php in the app/Http/Middleware directory. Add the following code to it like so:

<?php

namespace App\Http\Middleware;

use Closure;
use Auth0\SDK\JWTVerifier;

class Auth0Middleware
{
    /**
     * Run the request filter.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if(!$request->hasHeader('Authorization')) {
          return response()->json('Authorization Header not found', 401);
        }

        $token = $request->bearerToken();

        if($request->header('Authorization') == null || $token == null) {
          return response()->json('No token provided', 401);
        }

        $this->retrieveAndValidateToken($token);

        return $next($request);
    }

    public function retrieveAndValidateToken($token)
    {
        try {
            $verifier = new JWTVerifier([
              'supported_algs' => ['RS256'],
              'valid_audiences' => ['AUTH0_API_AUDIENCE'],
              'authorized_iss' => ['AUTH0_DOMAIN']
            ]);

            $decoded = $verifier->verifyAndDecode($token);
        }
        catch(\Auth0\SDK\Exception\CoreException $e) {
            throw $e;
        };
    }

}


In the retrieveAndValidateToken method, we created an instance of JWTVerifier to verify the token coming from the Authorization header. It checks the algorithm, the API audience, and the issuer to ensure the token is a valid one issued by Auth0.

Note: Replace the AUTH0_API_AUDIENCE and AUTH0_DOMAIN placeholders with the API audience and Auth0 domain values from your Auth0 dashboard.

Now, we want to assign the newly created middleware to our routes. The first step is to assign the middleware a short-hand key in bootstrap/app.php file’s call to the $app->routeMiddleware() method.

Go ahead and open up bootstrap/app.php and uncomment this line of code:

...
// $app->routeMiddleware([
//     'auth' => App\Http\Middleware\Authenticate::class,
// ]);
...


Once uncommented, replace the Authenticate::class with Auth0Middleware::class like so:

$app->routeMiddleware([
    'auth' => App\Http\Middleware\Auth0Middleware::class,
]);


Once the middleware has been defined in the HTTP kernel, as we have done above. We can now use the middleware key in the route options array in the routes/web.php file like so:

...
$router->group(['prefix' => 'api', 'middleware' => 'auth'], function () use ($router) {
  $router->get('authors',  ['uses' => '[email protected]']);

  $router->get('authors/{id}', ['uses' => '[email protected]']);

  $router->post('authors', ['uses' => '[email protected]']);

  $router->delete('authors/{id}', ['uses' => '[email protected]']);

  $router->put('authors/{id}', ['uses' => '[email protected]']);
});


We just secured all the API endpoints with JWT. If a user accesses these API endpoint/route without a valid access token or no token at all, it returns an error. Try it out.

Accessing any endpoint without an authorization header

Accessing any endpoint without any token provided

Accessing any endpoint without a valid access token

Now, let’s test it with a valid access token. Head over to the test tab of your newly created API on your Auth0 dashboard.

Grab the Access token from the Test tab

Grab the Access Token

Now use this access token in Postman by sending it as an Authorization header to make a POST request to api/people endpoint.

Accessing the endpoint securely

It validates the access token and successfully makes the POST request.

Wondering how to integrate the secure API with a frontend? Check out our amazing React and Vue.js authentication tutorials.

Conclusion

Well done! You have learned how to build and secure a rest API with the powerful PHP micro-framework, Lumen, and JWT. Need to use PHP to build your API or micro-service? I’d bet on Lumen as the tool of choice for speed and ease of use.

Check out the repo to get the code.

GraphQL vs REST: putting REST to rest

GraphQL vs REST: putting REST to rest

When you need to build an API, your mind will likely jump to REST, the de facto standard for API creation. However, this is about to change with GraphQL, as its popularity quickly rises.

When you need to build an API, your mind will likely jump to REST, the de facto standard for API creation. However, this is about to change with GraphQL, as its popularity quickly rises.

Not everyone fully understands yet what GraphQL is all about, or why it's being declared as the successor of REST, and that's exactly what I'll clear up in this article. Here I'll show off GraphQL's main features and the advantages that it has over REST, highlighting a few points in which both differ.

The goal is to provide a brief explanation to anyone who still hasn't got to know GraphQL, and clarify exactly what it does better than REST, for those who are still skeptic about this technology.

Let's start with the very basics.

What is GraphQL?

GraphQL is a query language for APIs that enables declarative data fetching in order to give the client the power to specify exactly the data that is needed from the API.

A question that I see asked a lot is:

Why was GraphQL created when we already have REST?
There are two main reasons why companies such as Facebook, Netflix and Coursera started developing alternatives to REST:

1. In the early 2010s there was a boom in mobile usage, which led to some issues with low-powered devices and sloppy networks. REST isn't optimal to deal with those problems;

2. As mobile usage increased, so did the number of different front-end frameworks and platforms that run client applications. Given REST's inflexibility, it was harder to develop a single API that could fit the requirements of every client.

If we go even further, we realize that the main reason why an alternative solution was identified was because most of the data used in modern web and mobile applications has a graph shape. For instance, newspieces have comments, and those comments may have features such as likes or spam flags, which are created or reported by users. This example describes how a graph looks like.

Consequently, Facebook started developing GraphQL. At the same time, Netflix and Coursera were also working on alternatives themselves. After Facebook open-sourced GraphQL, Coursera dropped their efforts and adopted the new tech. Netflix, however, continued developing their own REST alternative and later open sourced Falcor.

What GraphQL isn't

Now that we know what GraphQL is, I want to clarify what it is not, as I feel that there's still some confusion about it.

Firstly, it doesn't have anything to do with databases. It isn't an alternative to SQL or a brand new ORM.

Secondly, it isn't a REST replacement, but an alternative. You don't have to pick between one and the other, they can happily co-exist in the same project.

Last but not least, GraphQL isn't complicated or scary. It's quite easy to understand its declarative nature and exactly how it's possible to take the best from it.

GraphQL in context

Before moving on to the comparison with REST, I'll go through a simple GraphQL query where we can fetch a user as well as his or her name and age:

query {
  user {
    name
    age
  }
}

And the JSON response we'll get from it:

{
  "user": {
    "name": "Johnathan Joestar",
    "age": 27
   }
}

As I stated previously, GraphQL's declarative nature makes it incredibly easy to understand what's going on at all times, as we are basically writing JSON objects without the values.

Now that we have context, let's dive deep into GraphQL's features and the advantages that it has over REST.

GraphQL vs REST

In this section I'll go point by point through a practical example, comparing REST to GraphQL in order to demonstrate the flexibility of Facebook's query language.

Imagine that you have a blog, and you want the front page to show all the latest posts. In order to achieve this, you need to fetch the posts, so you will probably do something like this:

GET /api/posts

[
  {
    "title": "Cooler post",
    "subtitle": "...",
    "date": "07/05/2019"
  },
  {
    "title": "Cool post",
    "subtitle": "...",
    "date": "06/05/2019"
  }
]

But what if you want to see the author as well? You have three options to achieve this:

  • Fetch the authors from another resource:
GET /api/post/:id

{
  "post": {
    ...,
    "author": {
      "name": "Dio Brando"
    }
  }
}

  • Modify the resource to also return the author:
GET /api/posts

[
  {
    ...,
    "author": {
      "name": "Dio Brando"
    }
  },
  {
    ...,
    "author": {
      "name": "Johnathan Joestar"
    }
  }
]

  • Create a new resource that returns the posts with the author:
GET /api/postsWithAuthor

[
  {
    ...,
    "author": {
      "name": "Dio Brando"
    }
  },
  {
    ...,
    "author": {
      "name": "Johnathan Joestar"
    }
  }
]

Each of these approaches will create a problem of its own, so let's have a look at them one by one.

Under-fetching

With the first approach – fetching the authors from another resource – you'll end up with two server requests instead of one, and as you continue to scale, you may have even more requests to different endpoints in order to fetch all the needed data.

With GraphQL, this wouldn't happen. You would only have one request, and you wouldn't have to make multiple round trips to the server, as seen below:

query {
  posts {
    title
    subtitle
    date
    author {
      name
    }
  }
}

Over-fetching

Looking at the second approach – modifying the resource to also return the author – you can see that it solved the problem pretty nicely. However, changing a resource may have a secondary effect elsewhere on your application. More precisely, over-fetching.

Let's go back to your blog, but this time you also have a sidebar showing off the top monthly posts with their titles, subtitles and date, that is using the resource /api/posts. Since you modified the resource, now it also shows the author with it. However, we don't need it for the sidebar.

While this may not look like a problem, for users on limited data plans, having a website fetch useless data isn't ideal. Since GraphQL allows the client to only fetch the needed data, this problem wouldn't exist:

query {
  posts {
    title
    subtitle
    date
  }
}

Slow front-end development

Lastly, let's have a look at the last approach – creating a new resource that returns the posts with the author – since it's a common pattern to structure the endpoints according to the views in your project.

While this may solve problems such as the one described above, it also slows down the front-end development, since each specific view needs its specific endpoint. If at any point a view needs new data, the development has to slow down until the endpoint is updated.

Again, since GraphQL gives power to the client to fetch the needed data only, nothing slows down, as it's very simple to just add a new field to a query.

You would get from this:

query {
  posts {
    title
    subtitle
    date
  }
}

To this:

query {
  posts {
    title
    subtitle
    date
    author {
      name
    }
  }
}

REST vs GraphQL comparison recap

Let's just do a quick recap regarding the differences between REST and GraphQL:

  • GraphQL solves both over-fetching and under-fetching issues by allowing the client to request only the needed data;
  • Since the client now has more freedom in the fetched data, development is much faster with GraphQL than what it would be with REST.

Now we'll move on to a more in-depth overview of GraphQL's unique features.

GraphQL's features overview

Now that we know how it stacks up against REST, let's talk about some of the features that are unique to GraphQL.

Schema and Type System

GraphQL uses its own type system to define the schema of an API, with its syntax called Schema Definition Language (SDL). The schema serves as a contract between the server and the client to define how a client can access the data.

Once the schema is defined, the front-end and back-end teams can work independently, as the front-end can be easily tested with mock data. The front-end can also get useful information from the schema, such as its types, queries and mutations using GraphiQL or introspection. The schema also provides type safety, which is a plus for the front-end and back-end development, as it catches type errors early.

A schema example:

type User {
  name: String!
  age: Int
  posts: [Post!]!
}

type Post {
  title: String!
  subtitle: String!
  body: String!
  date: String!
  author: User!
}

type Query {
  users: [User!]!
  user(name: String!): User!
  posts: [Post!]!
  post(title: String!): Post!
}

type Mutation {
  createUser(name: String!, age: Int): User!
  createPost(title: String!, subtitle: String!, body: String!): Post!
}

GraphQL IDE

This is one of the most useful features of GraphQL development. A GraphQL IDE takes advantage of its self-documenting nature to make development a breeze.

Using GraphiQL or GraphQL Playground, you can just inspect your schema and even run queries and mutations to test out your API.

GraphQL Playground

Wrap up

GraphQL provides a smooth and fast development environment with its declarative and flexible nature, offering many improvements over REST. Despite being relatively new, it has already been adopted by companies such as Facebook, GitHub and many more .

It already has a large community and a vibrant ecosystem, and was already implemented in several popular languages, such as JavaScript, Go and Java.

While this post only dipped the toes into the ocean that is GraphQL, its website has a plethora of information and is an amazing place to learn and start using GraphQL.

With all this being said, it's not a perfect technology, and it still has a couple of drawbacks when compared with REST. But considering how young it is, the future looks incredibly bright for GraphQL.

PHP with Vue.js & MySQL: REST API CRUD Tutorial

PHP with Vue.js & MySQL: REST API CRUD Tutorial

PHP with Vue.js & MySQL: REST API CRUD Tutorial - In this tutorial, we'll build a RESTful CRUD application with PHP & MySQL in the backend and Vue.js in the frontend. We'll also be using Axios for sending Ajax request to PHP from Vue.

The Vue.js library, Axios client and Ajax technology allows you to fetch and display data in your application without the need to refresh the whole page each time.

For database we'll be using MySQL, the most popular database used by PHP developers.

Creating the MySQL Database

In your terminal, start the MySQL client using:

mysql -u root -p

Enter your password when prompted and hit Enter.

Next, create a database using the following SQL statement:

mysql> create database vuedb;

Next, create the following SQL table in your vuedb database:

mysql> use vuedb;
mysql> CREATE TABLE `contacts` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  `city` varchar(100),
  `country` varchar(100),
  `job` varchar(100)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Create The PHP & MySQL CRUD App

Now, let's create a PHP and MySQL CRUD application. Open a new terminal, navigate to your working directory then create a folder for your project:

$ cd ~/demos
$ mkdir php-vuejs-crud

Next, navigate in your project's folder and add an index.php file:

$ cd php-vuejs-crud
$ touch index.php

Open the index.php file and add the following code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>PHP| MySQL | Vue.js | Axios Example</title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
</body>
</html>

We first include Vue.js and Axios from their CDNs.

Next, in the body of the document, add a <table> to display fetched data:

<h1>Contact Management</h1>
<div id='vueapp'>

<table border='1' width='100%' style='border-collapse: collapse;'>
   <tr>
     <th>Name</th>
     <th>Email</th>
     <th>Country</th>
     <th>City</th>
     <th>Job</th>

   </tr>

   <tr v-for='contact in contacts'>
     <td>{{ contact.name }}</td>
     <td>{{ contact.email }}</td>
     <td>{{ contact.country }}</td>
     <td>{{ contact.city }}</td>
     <td>{{ contact.job }}</td>
   </tr>
 </table>

We use the v-for directive to iterate over the contacts array and display each contact.

Next, add a <form> tag:

</br>

    <form>
      <label>Name</label>
      <input type="text" name="name" v-model="name">
</br>
      <label>Email</label>
      <input type="email" name="email" v-model="email">
      </br>
      <label>Country</label>
      <input type="text" name="country" v-model="country">
      </br>
      <label>City</label>
      <input type="text" name="city" v-model="city">
      </br>
      <label>Job</label>
      <input type="text" name="job" v-model="job">
      </br>
      <input type="button" @click="createContact()" value="Add">
    </form>

</div>

We use the v-model directive to bind the input fields to their corresponding variables in the Vue instance we'll be creating next. And we use the @click event to bind the click event of the button to the createContact() method that will be defined in the Vue instance.

Next, add a <script> tag and create a Vue app:

<script>
var app = new Vue({
  el: '#vueapp',
  data: {
      name: '',
      email: '',
      country: '',
      city: '',
      job: '',
      contacts: []
  },
  mounted: function () {
    console.log('Hello from Vue!')
    this.getContacts()
  },

  methods: {
    getContacts: function(){
    },
    createContact: function(){
    },
    resetForm: function(){
    }
  }
})    
</script>
</body>
</html>    

We declared three methods, let's implement them!

The getContacts() method gets contacts from the PHP endpoint using Axios:

    getContacts: function(){
        axios.get('api/contacts.php')
        .then(function (response) {
            console.log(response.data);
            app.contacts = response.data;

        })
        .catch(function (error) {
            console.log(error);
        });
    }

The createContact() methods creates a new contact in the MySQL database by sending a POST request with Axios and FormData:

    createContact: function(){
        console.log("Create contact!")

        let formData = new FormData();
        console.log("name:", this.name)
        formData.append('name', this.name)
        formData.append('email', this.email)
        formData.append('city', this.city)
        formData.append('country', this.country)
        formData.append('job', this.job)

        var contact = {};
        formData.forEach(function(value, key){
            contact[key] = value;
        });

        axios({
            method: 'post',
            url: 'api/contacts.php',
            data: formData,
            config: { headers: {'Content-Type': 'multipart/form-data' }}
        })
        .then(function (response) {
            //handle success
            console.log(response)
            app.contacts.push(contact)
            app.resetForm();
        })
        .catch(function (response) {
            //handle error
            console.log(response)
        });
    }

The resetForm() method resets the form:

    resetForm: function(){
        this.name = '';
        this.email = '';
        this.country = '';
        this.city = '';
        this.job = '';
    }

Create an API Endpoint

Now, let's create an endpoint that provides contacts data in a JSON format to our Vue frontend.

Create an api folder inside your project's root folder:

$ mkdir api

Navigate inside the api folder and create a contacts.php file and add the following content:

<?php
$host = "localhost"; 
$user = "root"; 
$password = "YOUR_MYSQL_DB_PASSWORD"; 
$dbname = "vuedb"; 
$id = '';

$con = mysqli_connect($host, $user, $password,$dbname);

$method = $_SERVER['REQUEST_METHOD'];
$request = explode('/', trim($_SERVER['PATH_INFO'],'/'));
//$input = json_decode(file_get_contents('php://input'),true);


if (!$con) {
  die("Connection failed: " . mysqli_connect_error());
}


switch ($method) {
    case 'GET':
      $id = $_GET['id'];
      $sql = "select * from contacts".($id?" where id=$id":''); 
      break;
    case 'POST':
      $name = $_POST["name"];
      $email = $_POST["email"];
      $country = $_POST["country"];
      $city = $_POST["city"];
      $job = $_POST["job"];

      $sql = "insert into contacts (name, email, city, country, job) values ('$name', '$email', '$city', '$country', '$job')"; 
      break;
}

// run SQL statement
$result = mysqli_query($con,$sql);

// die if SQL statement failed
if (!$result) {
  http_response_code(404);
  die(mysqli_error($con));
}

if ($method == 'GET') {
    if (!$id) echo '[';
    for ($i=0 ; $i<mysqli_num_rows($result) ; $i++) {
      echo ($i>0?',':'').json_encode(mysqli_fetch_object($result));
    }
    if (!$id) echo ']';
  } elseif ($method == 'POST') {
    echo json_encode($result);
  } else {
    echo mysqli_affected_rows($con);
  }

$con->close();

Finally, you can serve your PHP application using the following command from the root of your project:

$ php -S 127.0.0.1:8080

This is a screenshot of the application, after posting some data using the form:

For the same styling, add the following CSS:

<style>
    input {
  width: 100%;
  padding: 2px 5px;
  margin: 2px 0;
  border: 1px solid red;
  border-radius: 4px;
  box-sizing: border-box;
}

input[type=button]{
  background-color: #4CAF50;
  border: none;
  color: white;
  padding: 4px 7px;
  text-decoration: none;
  margin: 2px 1px;
  cursor: pointer;
}
th, td {
  padding: 1px;
  text-align: left;
  border-bottom: 1px solid #ddd;
  
}
tr:hover {background-color: #f5f5f5;}

</style>

Conclusion

In this tutorial, we've used PHP, MySQL, Vue.js and Axios to create a simple REST API CRUD example application.