Blog postAngular app with PHP backend: part 1

Learn to code Angular app with PHP backend: part 1


Angular is the most advanced and versatile frontend framework, but to build a full-blown application, you need a backend. In this series of tutorials, you will learn to code an Angular with a PHP backend.

The code in the first tutorial of the series fetches the data from the server side and then displays it in the Angular side of the application.

In the following tutorials, you'll learn how to add, update, and delete items.

Demo for the Angualr and PHP application

All the tutorials in the series about developing Angular app with a PHP backend:

  1. How to install Angular?
  2. What is REST API? In plain English
  3. What is Angular Observable?
  4. Angular app with PHP backend: part 1 (GET)
  5. Angular app with PHP backend: part 2 (POST)
  6. Angular app with PHP backend: part 3 (PUT)
  7. Angular app with PHP backend: part 4 (DELETE)

Click to see the code in action

You can dowload the source code from the conclusion section

# 1. Seting the app

If you do not know how to set up an Angular project, please read the Angular Installation guide I posted on the site.

You need to install Angular CLI if you haven't already done it:

> npm install -g @angular/cli

Generate a new Angular app with the name of "cars":

> ng new cars

Now, you need to answer the following questions in order to set the app:

? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? (Use arrow keys)
❯ CSS 
  SCSS   [ https://sass-lang.com/documentation/syntax#scss                ] 
  Sass   [ https://sass-lang.com/documentation/syntax#the-indented-syntax ] 
  Less   [ //lesscss.org                                             ] 
  Stylus [ https://stylus-lang.com                                        ]
  • You don't need the routing for this project. The stylesheet format needs to be CSS.
  • You may choose otherwise but for now all you need is just a simple app.

Once the installation has finished, cd into the app's folder:

> cd cars/

Then serve the app:

> ng serve --o

It may take a while until the installation finishes and the app launches, but if everything is working according to plan you need to see Angular's default homepage in the browser:

First look at the generic page that the Angular app created

To give the app a nice look, include the link to the Bootstrap's (CSS framework) stylesheet in the index.html header.

src/index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Cars</title>
  <base href="/">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>

Here I use a CDN as the source of the stylesheet.

# 2. Add the HttpClientModule to the project

Angular's preferred way to communicate with the server side is through the HttpClient module.

To be able to use the HttpClient, you need to import it into the root module of the application:

src/app/app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  • It is not enough to import the module you should also add it's symbol to the imports array.

After importing, you will be able to use the module in the various parts of the application, such as in the components and services.

# 3. Add the Car interface

A car is not just a thing, and since you work with TypeScript, you better define the type. You will do this with the Car interface, which you need to add to the app. For this, manually create a car.ts file in the src/app folder, and put the following code inside:

src/app/car.ts

export interface Car {
  model: string;
  price: number;
  id?: number;
}

Besides the price and model name, the interface contains an id which is an optional field, hence the question mark.

# 4. Place the method to communicate with the server in a service

While you can call AJAX directly from the components, this is not a best practice because you may want to use the same methods in different parts of the application. Therefore, it is better to put these methods in a dedicated service. In our case, it will be a service with the name of car.service.

To generate the service run the following command in the CLI:

> ng generate service car --flat

The command includes the --flat flag because you want the service to contain only files instead of being locked in a folder.

Inside the generated file you will see the following code:

src/app/car.service.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CarService {
}

The Injectable decorator allows the service to participate in the dependency injection (DI) system. Which means that on the one hand, it can have dependencies (i.e., the HttpClient), and on the other hand, it can be injected, for example into the components.

But what is a dependency? A dependency is when one class depends on another for its function.

A dependency is when one class depends on another for its function.

Angular's way of managing the app dependencies is through the Dependency Injection system or DI, whose job it is to create for us the objects that we need in the right place at the right time.

A common practice of creating objects in object-oriented programming is by using the new keyword. For example, if you are interested in an HttpClient object, then you might be tempted to write the following code:

private http = new HttpClient;

This is not the Angular way because when developing with Angular it is strongly advised to use the Dependency Injection (DI) system to manage the objects that the app needs for its function.

when developing with Angular it is strongly advised to use the Dependency Injection (DI) system to manage the objects that the app needs.

For example, the CarService needs an HttpClient object and various other dependencies to communicate with the server but it doesn't need to bother us since the DI system does the heavy lifting for us.

Replace the code inside the service file with this:

src/app/car.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { map } from 'rxjs/operators';

import { Car } from './car';

@Injectable({
  providedIn: 'root'
})
export class CarService {
  constructor(private http: HttpClient) { }
}

The dependency injection is done in the constructor, by defining the private http variable as belonging to the HttpClient type, which instructs Angular to handle the creation of the HttpClient object for us by using the DI.

Importing from the RxJS library allows us to work with the Observable that Angular wraps around the data that is coming from the server. Using an Observable instead of a standard callback to handle asynchronous code offers several advantages, including multiple operators that facilitate data handling, as well as the ability to listen to data that the server emits repeatedly over time.

Want to know more about working with Observables in Angular? read the tutorial What is Observable in Angular?

# 5. Displaying the list of cars coming from the server

To get the list of cars coming from the server, write the following code inside the CarService class:

src/app/car.service.ts

baseUrl = 'http://localhost/api';
                
constructor(private http: HttpClient) { }
                
getAll() {
  return this.http.get(`${this.baseUrl}/list`).pipe(
    map((res: any) => {
      return res['data'];
    })
  );
}

The getAll() method returns the list of cars wrapped inside an Observable:

getAll() {
}

We use the HttpClient get() method to fetch the data from the server side:

getAll() {
  return this.http.get(`${this.baseUrl}/list`)
}

The data returned from the server is the list of cars wrapped inside an external array (a common case when consuming APIs).

This is how the data returned from the server looks like:

{
  data: 
  [
    {
      id: "1",
      model: "subaru",
      price: "120000"
    },
    {
      id: "2",
      model: "mazda",
      price: "160000"
    }
  ]
}

We'll get to writing the code for the server side in a short time.

Since we are only interested in the list of cars in the innermost array we need to extract the list. For this job, we use the RxJS map() operator:

src/app/car.service.ts

getAll() {
  return this.http.get(`${this.baseUrl}/list`).pipe(
    map((res) => {
      return res['data'];
    })
  );
}

Note that in order for the observable to work, it is not enough that you have the get() method in the service, you also need to actively subscribe to the data in the component.

The full code for the service:

src/app/car.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { map } from 'rxjs/operators';

import { Car } from './car';

@Injectable({
  providedIn: 'root',
})
export class CarService {
  baseUrl = 'http://localhost/api';

  constructor(private http: HttpClient) {}

  getAll() {
    return this.http.get(`${this.baseUrl}/list`).pipe(
      map((res: any) => {
        return res['data'];
      })
    );
  }
}

# 6. The code in the component which subscribes to the data

To be able to display the data to the client, you need a method inside the component which subscribes to the data that the service fetches from the server.

Write the following code inside the component file:

src/app/app.component.ts

import { Component, OnInit } from '@angular/core';

import { Car } from './car';
import { CarService } from './car.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  cars: Car[] = [];
  error = '';
  success = '';
        
  constructor(private carService: CarService) {
  }
        
  ngOnInit() {
    this.getCars();
  }
        
  getCars(): void {
  }
}

The variable cars inside the component stores the array of cars retrieved from the server.

In the constructor, you inject the carService dependency so that the service will be available to all the methods of the controller as soon as Angular creates an object out of the controller.

Inside the ngOnInit() lifecycle hook, you call the getCars() method just after the creation of the controller by Angular.

ngOnInit is a special lifecycle hook provided by Angular that runs immediately after the constructor finishes injecting the dependencies, so it is a good place to get the array of cars into the controller.

Now add the getCars() method that subscribers to the data that comes from the service:

src/app/app.component.ts

getCars(): void {
  this.carService.getAll().subscribe(
    (data: Car[]) => {
      this.cars = data;
      this.success = 'successful retrieval of the list';
    },
    (err) => {
      console.log(err);
      this.error = err;
    }
  );
}
  • The first callback is for handling the successful retrieval of the list of cars.
  • The second callback handles errors.

When we subscribe to observable we expect one of three results:

  • Getting the requested data from the server side (the array of cars).
  • An error on the server side.
  • An indication that the stream of data has finished.

In our case, only the first two results are relevant because the action is not expected to end since the list can be updated at any time with the items that our users add to the list (as you'll see in later tutorials).

Would you like to deepen your understanding of Observables? Read the tutorial that explains the subject of Observables plain English.

Now you can show the list of cars in the HTML template by using the code:

src/app/app.component.html

<div *ngIf="error">{{error}}</div>
<div *ngIf="success">{{success}}</div>
    
<div id="theList">
  <h2>The list</h2>
  <ul>
    <li *ngFor="let item of cars">{{item.model}} | {{item.price}} </li>
  </ul>
</div>

The list will be printed to the screen within the ngFor loop from the array of cars, once we set up the PHP backend service and have cars to display.

# 7. The server side of the project

I wrote server-side as a simple PHP script with a MySQL database. The same principles can be applied to any paradigm, framework or language.

For this tutorial I used XAMPP environment which runs on my computer.

The following is the MySQL code for generating the database table:

CREATE TABLE IF NOT EXISTS `cars` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `model` varchar(255) NOT NULL DEFAULT '',
  `price` int (10) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Put the PHP scripts in a folder with the name of api/ on the server.

The .htaccess file is the configuration file of the Apache server, in which you specify two rules:

  1. A rule to remove the PHP extension from the file names.
  2. Headers to allow the Angular part of the application to transfer data and perform operations on the PHP server.

api/.htaccess

# Remove the php extension from the filename
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

# Set the headers for the restful api
Header always set Access-Control-Allow-Origin http://localhost:4200
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"

The header part of the .htacess file:

Header always set Access-Control-Allow-Origin "http://localhost:4200"

Instructs the server to give the Angular app the necessary privileges even though the web address is different.

The rest of the headers permit the exchange of data between the Angular side and the server side using the HTTP protocol methods:

GET

To retrieve the data about a single resource* or a list of resources

POST

To store a new resource

PUT

To update the data that is already found on the server

DELETE

To destroy a resource

* A resource is roughly equivalent to a single row in the database. In our app, every car is a resource.

The application conforms to the REST API architecture on which you can read in the following tutorial.

The connect.php script creates the connection with the database:

api/connect.php

<?php

// db credentials
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '');
define('DB_NAME', 'angular_db');

// Connect with the database.
function connect()
{
  $connect = mysqli_connect(DB_HOST ,DB_USER ,DB_PASS ,DB_NAME);

  if (mysqli_connect_errno($connect)) {
    die("Failed to connect:" . mysqli_connect_error());
  }

  mysqli_set_charset($connect, "utf8");

  return $connect;
}

$con = connect();

The api/list.php script receives a GET request from the Angular side of the application and returns the list of cars stored in the database.

list.php

<?php
/**
 * Returns the list of cars.
 */
require 'connect.php';
    
$cars = [];
$sql = "SELECT id, model, price FROM cars";

if($result = mysqli_query($con,$sql))
{
  $cr = 0;
  while($row = mysqli_fetch_assoc($result))
  {
    $cars[$cr]['id']    = $row['id'];
    $cars[$cr]['model'] = $row['model'];
    $cars[$cr]['price'] = $row['price'];
    $cr++;
  }
    
  echo json_encode(['data'=>$cars]);
}
else
{
  http_response_code(404);
}

# Conclusion

In the first tutorial in the series about developing an Angular and PHP application, we laid the foundations for building the app. We explained what is a service and why it is a good thing to put the methods that communicate with the server in a dedicated service. You learned about the HttpClient module that Angular uses to communicate data via AJAX and that it is based on the pattern of Observable. We also started writing the code for the PHP backend which supplies the API for the app.

In the following tutorial, you will learn how to add new items to the list with the help of the post() method.

Click to download the source code for the tutorials

comments powered by Disqus