This tutorial teaches you how to build a simple CRUD application with a Laravel backend API and an Angular frontend.

Laravel is a popular PHP framework for Web application development and it’s a pretty good choice if you’re starting a new project today for multiple reasons:

Laravel is a well-architectured framework that’s easy to pick up and write elegant code, but it’s powerful as well. It contains many advanced features out-of-the-box: Eloquent ORM, support for unit/feature/browser tests, job queues, and many more. There’s an abundance of great learning resources and it boasts one of the largest communities on the net, so it’s easy to find developers who are familiar with it.

Laravel includes a decent templating engine if you’re going old school (by generating HTML on the server side) and it also comes out of the box with a great frontend build tool (the webpack-based Laravel Mix) and Vue.js for building single-page applications. Because of this, the combination of Laravel + Vue.js has turned into the de-facto standard. However, Laravel might be choosing Vue.js but it doesn’t mean you are limited to it!

One of the best ‘hidden’ features of Laravel is that it’s very easy to use it to create a REST-ful API that can drive a frontend built in your preferred framework. Of course, you can also go with the light-weight version of Laravel, Lumen, if you need a high-performance API with minimum overhead and bootstrapping time of less than 40 ms, but for most purposes, the full-featured Laravel will do just fine. Today, I’m going to show you how easy it is to set up a Laravel API that is consumed by an Angular 6 application. We’ll use Okta for user authentication and authorization in our app, which will allow us to implement security the right way without any hassle.

Before you start, you’ll need to set up a development environment with PHP 7 and Node.js 8+/npm. You will also need an Okta developer account.

Why Use Okta for Authentication?

Well, we might be biased, but we think Okta makes identity management easier, more secure, and more scalable than what you’re used to. Okta is an API service that allows you to create, edit, and securely store user accounts and user account data, and connect them with one or more applications. Our API enables you to:

Register for a forever-free developer account, and when you’re done, come back to learn more about building a secure CRUD app with Laravel and Angular.

Angular and Laravel CRUD Application

Today we’ll build a simple trivia game interface that will allow you to run trivia games for your friends. Here’s what the finished app will look like:

Here’s one possible way to run the game as the host:

You can, of course, make up your own rules as well.

Create a Free Okta Developer Account

Let’s set up our Okta account so it’s ready when we need it.

Before you proceed, you need to log into your Okta account (or create a new one for free) and set up a new OIDC app. You’ll mostly use the default settings. Make sure to take note of your Okta domain and the Client ID generated for the app.

Here are the step-by-step instructions:

Go to the Applications menu item and click the ‘Add Application’ button:

Select ‘Single Page Application’ and click ‘Next’.

Set a descriptive application name, add http://localhost:3000/login as a Login redirect URI, and click Done. You can leave the rest of the settings as they are.

Install and Configure the Laravel Application

We will follow the installation instructions from the official Laravel documentation (https://laravel.com/docs/5.7/installation)

First, let’s install the ‘laravel’ command globally on our system through composer. Then we’ll create a new Laravel project, navigate to it and start the development PHP server:

composer global require laravel/installer
laravel new trivia-web-service
cd trivia-web-service
php artisan serve


Next, we’ll create a MySQL database and user for our app (you are free to use a different database engine if you prefer):

mysql -uroot -p
CREATE DATABASE trivia CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'trivia'@'localhost' identified by 'trivia';
GRANT ALL on trivia.* to 'trivia'@'localhost';
quit


Now let’s edit our .env file and enter our database credentials:

.env

DB_DATABASE=trivia
DB_USERNAME=trivia
DB_PASSWORD=trivia


Create a Backend API with Laravel

We’ll start by creating a model and a migration for our Player entity.

php artisan make:model Player -m
Model created successfully.
Created Migration: 2018_10_08_094351_create_players_table


The -m option is short for –migration and it tells Artisan to create one for our model.

Edit the migration file and update the up() method:

database/migrations/2018_10_08_094351_create_players_table.php

public function up()
{
    Schema::create('players', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->integer('answers')->default(0);
        $table->integer('points')->default(0);
        $table->timestamps();
    });
}


Then run the migration to create the table:

php artisan migrate


Edit the model file and add a $fillable attribute to the class so we can define which fields we can mass-assign in create() and update() operations on the model:

app/Player.php

class Player extends Model
{
    protected $fillable = ['name', 'answers', 'points'];
}


Now we’ll create two API resources: Player (dealing with an individual player) and PlayerCollection (dealing with a collection of players).

php artisan make:resource Player
php artisan make:resource PlayerCollection


Modify the transformation functions toArray() of the resources:

app/Http/Resources/Player.php

public function toArray($request)
{
    return [
        'id'         => $this->id,
        'name'       => $this->name,
        'answers'    => (int) $this->answers,
        'points'     => (int) $this->points,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}


app/Http/Resources/PlayerCollection.php

public function toArray($request)
{
    return [
        'data' => $this->collection
    ];
}


We can now create the routes and controller for our REST API.

php artisan make:controller PlayerController


routes/api.php

Route::get('/players', 'PlayerController@index');
Route::get('/players/{id}', 'PlayerController@show');
Route::post('/players', 'PlayerController@store');
Route::post('/players/{id}/answers', 'PlayerController@answer');
Route::delete('/players/{id}', 'PlayerController@delete');
Route::delete('/players/{id}/answers', 'PlayerController@resetAnswers');


app/Http/Controllers/PlayerController.php

...
use App\Player;
use App\Http\Resources\Player as PlayerResource;
use App\Http\Resources\PlayerCollection;
...

class PlayerController extends Controller
{
    public function index()
    {
        return new PlayerCollection(Player::all());
    }

    public function show($id)
    {
        return new PlayerResource(Player::findOrFail($id));
    }

    public function store(Request $request)
    {
        $request->validate([
            'name' => 'required|max:255',
        ]);

        $player = Player::create($request->all());

        return (new PlayerResource($player))
                ->response()
                ->setStatusCode(201);
    }

    public function answer($id, Request $request)
    {
        $request->merge(['correct' => (bool) json_decode($request->get('correct'))]);
        $request->validate([
            'correct' => 'required|boolean'
        ]);

        $player = Player::findOrFail($id);
        $player->answers++;
        $player->points = ($request->get('correct')
                           ? $player->points + 1
                           : $player->points - 1);
        $player->save();

        return new PlayerResource($player);
    }

    public function delete($id)
    {
        $player = Player::findOrFail($id);
        $player->delete();

        return response()->json(null, 204);
    }

    public function resetAnswers($id)
    {
        $player = Player::findOrFail($id);
        $player->answers = 0;
        $player->points = 0;

        return new PlayerResource($player);
    }
}


The API allows us to get the list of all players or an individual player’s data, add/delete players, mark correct/incorrect answers by a player and reset the answers and points data of a player. There’s validation of the requests and the code generates JSON responses with the appropriate status codes - not bad at all for such a small amount of code.

To test the get methods, add some dummy data to the database (you can, of course, use the Laravel factories with the Faker library to generate data) and then access these URLs:

If you want to test the post/put/delete requests (for example with Postman), make sure to set the following header for each request:

Accept: “application/json”

so the validation errors will be returned as JSON.

Install Angular and Create the Frontend Application

We will follow the official Angular documentation (https://angular.io/guide/quickstart) and install the Angular CLI globally, then we’ll create a new project and start the server.

sudo npm install -g @angular/cli@^6.1
ng new trivia-web-client-angular
cd trivia-web-client-angular
ng --version
Angular CLI: 6.1.5
Angular: 6.1.9
ng serve


Navigating to http://127.0.0.1:4200/ now opens the default Angular application.

Next, we’ll add the Bulma framework (because everyone else is using Bootstrap, but we like to mix things up a bit, right):

npm install --save bulma


Add to .angular.json:

"styles": [
  ...,
  "node_modules/bulma/css/bulma.min.css"
]


Run the server again because changes to angular.json are not picked up automatically:

ng serve


Customize the Main Layout in Angular

Replace the default HTML layout:

src/app/app.component.html

<div style="text-align:center">
    <section class="section">
        <div class="container">
            <nav class="navbar" role="navigation" aria-label="main navigation">
                <div class="navbar-menu is-active buttons">
                    <button class="button is-link">Home</button>
                    <button class="button is-link">Trivia Game</button>
                </div>
            </nav>
        </div>
    </section>
</div>


Let’s create our two main components:

ng generate component Home
ng generate component TriviaGame


Adding routing:

src/app/app.module.ts

import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
    { path: '', component: HomeComponent, pathMatch: 'full' },
    { path: 'trivia', component: TriviaGameComponent },
    { path: '**', redirectTo: '', pathMatch: 'full' }
];


In the imports section:

imports: [
    BrowserModule,
    RouterModule.forRoot(routes)
],


Adding routing links and the router outlet (Replace the

#laravel #angular #php #angular.js

Build a Basic CRUD App with Laravel and Angular
4 Likes64.50 GEEK