One place for hosting & domains

      How to Generate a Short and Unique Digital Address for Any Location Using AngularJS and PHP


      Introduction

      Postal addresses are usually lengthy and sometimes difficult to remember. There are a number of scenarios where a shorter address would be desirable. For example, having the ability to send a short address consisting of only a couple of characters could ensure faster delivery of emergency ambulance services. Pieter Geelen and Harold Goddijn developed the Mapcode system in 2001 to make it easy to create a short-form address for any physical address in the world.

      In this tutorial, you will develop a web app that uses the Google Maps API to generate a short digital address for any address of your choice. You will do this by cloning the base code for this app from GitHub and then adding code to it that will make it fully functional. This app will also be able to retrieve the original physical address from a given mapcode.

      Prerequisites

      In order to complete this tutorial, you will need the following:

      Step 1 — Getting a Google API Key

      In this tutorial, you will use JavaScript to create an interface to Google Maps. Google assigns API keys to enable developers to use the JavaScript API on Google Maps, which you will need to obtain and add to your web app’s code.

      To get your own API key, head to Google’s “Get API Key” page. Click on the GET STARTED button in Step 1, and a pop-up will open as shown in the following image:

      Select Maps by clicking the check box and hit CONTINUE. If you aren’t already logged into a Google account, you will be asked to do so. Then, the window will ask you to provide a name for the project, which can be anything you’d like:

      Following this, it will ask you to enter your billing information. Note that Google provides API keys as part of a free trial, but it requires you to set up and enable billing in order retrieve them.

      After entering this information, your API key will appear on the screen. Copy and store it in a location where you can easily retrieve it, as you will need to add it to your project code later on.

      After obtaining your API key, you can begin building the foundation of your application by creating a MySQL database.

      Step 2 — Creating the Database

      The web application described in this tutorial accepts an address from the user and generates a mapcode for it along with the latitude and longitude of the specified location. You will store this data in a MySQL database so that you can retrieve it later on just by entering the respective digital address.

      Begin by opening the MySQL shell and authenticating with your password:

      At the prompt, create a database called digitaladdress using the following command:

      • CREATE DATABASE IF NOT EXISTS `digitaladdress`;

      Next, select this new database so that you can create a table within it:

      After selecting the digitaladdress database, create a table called locations within it to store the physical address, its longitude, latitude, and the mapcode that your application will create from this data. Run the following CREATE TABLE statement to create the locations table within the database:

      • CREATE TABLE `locations` (
      • `digitaladdress` varchar(50) DEFAULT NULL,
      • `state` varchar(30) DEFAULT NULL,
      • `zip` varchar(30) DEFAULT NULL,
      • `street` varchar(30) DEFAULT NULL,
      • `town` varchar(30) DEFAULT NULL,
      • `house` varchar(30) DEFAULT NULL,
      • `latitude` varchar(30) DEFAULT NULL,
      • `longitude` varchar(30) DEFAULT NULL,
      • KEY `digitaladdress` (`digitaladdress`)
      • );

      This table has eight columns: digitaladdress, state, zip, street, town, house, latitude, and longitude. The first column, digitaladdress, is indexed using the KEY command. Indexes in MySQL function similarly to how they work in an encyclopedia or other reference work. Any time you or your application issue a query containing a WHERE statement, MySQL reads every entry in each column, row-by-row, which can become an extremely resource-intensive process as your table accumulates more and more entries. Indexing a column like this takes the data from the column and stores it alphabetically in a separate location, which means that MySQL will not have to look through every row in the table. It only has to find the data you're looking for in the index and then jump to the corresponding row in the table.

      After adding this table, exit the MySQL prompt:

      With your database and table set up and your Google Maps API key in hand, you're ready to create the project itself.

      Step 3 — Creating the Project

      As mentioned in the introduction, we will clone the base code for this project from GitHub and then add some extra code to make the application functional. The reason for this, rather than walking you through the process of creating each file and adding all the code yourself, is to speed up the process of getting the app running. It will also allow us to focus on adding and understanding the code that allows the app to communicate with both the Google Maps and Mapcode APIs.

      You can find the skeleton code for the full project on this GitHub project page. Use the following git command to clone the project to your server:

      • git clone https://github.com/do-community/digiaddress.git

      This will create a new folder called digiaddress in your home directory. Move this directory to your server's web root. If you followed the LAMP stack tutorial linked in the prerequisites, this will be the /var/www/html directory:

      • sudo mv digiaddress/ /var/www/html/

      This project contains several PHP and JS files to which you'll add some code later on in this tutorial. To view the directory structure, first install the tree package using apt:

      Then run the tree command with the digiaddress directory given as an argument:

      • tree /var/www/html/digiaddress/

      Output

      digiaddress/ ├── README.md ├── db.php ├── fetchaddress.php ├── findaddress.php ├── generateDigitalAddress.php ├── geoimplement.php ├── index.php └── js ├── createDigitialAddressApp.js └── findAddressApp.js

      You can see from this output that the project consists of six PHP files and two JavaScript files. Together, these files create the application's two main functionalities: creating a mapcode from a physical address, and decoding a mapcode to retrieve the original physical address. The following files enable the first functionality:

      • index.php
      • geoimplement.php
      • generateDigitialAddress.php
      • db.php
      • createDigitialAddressApp.js

      The index.php file contains the code for the application's user interface (UI), which consists of a form where users can enter a physical address. The index.php file calls the geoimplement.php file any time a user submits the form. geoimplement.php makes a call to the Google Maps API and passes the address along to it. The Google server then responds with a JSON containing the specified address's information, including its latitude and longitude. This information is then passed to the generateDigitalAddress.php file which calls the Mapcode API to obtain a mapcode for the given location, as specified by its latitude and longitude. The resulting mapcode, along with the latitude, longitude, and the physical address, are then stored in the database that you created in Step 2. db.php acts as a helper for this operation. The createDigitalAddressApp.js file performs a number of operations that control the UX elements seen in the app, including setting a marker and boundary rectangle on the Google Maps interface.

      The remaining three files enable the second function of the application — that is, retrieving a physical address from a given mapcode:

      • findaddress.php
      • fetchaddress.php
      • findAddressApp.js

      The findaddress.php file defines the application UI, which is distinct from the one defined in index.php. The application accepts a previously-generated mapcode as an input and displays the corresponding physical address stored in the database. Whenever a user submits this form, findaddress.php sends a call to fetchaddress.php which then retrieves the respective mapcode from the database. The findAddressApp.js file contains the helper code for setting a marker and a boundary rectangle on the Google Maps interface.

      Test the installation by visiting http://your_server_ip/digiaddress in your browser, making sure to change your_server_ip to reflect your server's IP address.

      Note: If you don't know your server's IP address, you can run the following curl command. This command will print the page content of icanhazip.com, a website that shows the IP address of the machine accessing it:

      • curl http://icanhazip.com

      Once there, you will see this heading at the top of your browser window:

      Generate Digital Address
      

      This confirms that you have correctly downloaded the project files. With that, let us proceed with the development of the app's primary function: generating a mapcode.

      Step 4 — Developing the Application's UI

      While the boilerplate code for the application interface is included in the files you downloaded in the previous step, you still need to make a few changes and additions to some of these files to make the application functional and engaging for users. We will get started with updating the code to develop the application's UI.

      Open the index.php file using your preferred editor. Here, we'll use nano:

      • nano /var/www/html/digiaddress/index.php

      Look for the following line of code:

      /var/www/html/digiaddress/index.php

      . . .
      <script async defer src="https://maps.googleapis.com/maps/api/js?key=<YOUR KEY>"></script>
      . . .
      

      Replace <YOUR KEY> with the Google API key you obtained in Step 1. After adding your API key, the line should look similar to this:

      /var/www/html/digiaddress/index.php

      . . .
      <script async defer src="https://maps.googleapis.com/maps/api/js?key=ExampleAPIKeyH2vITfv1eIHbfka9ym634Esw7u"></script>
      . . .
      

      Next, find the following comment in the index.php file:

      /var/www/html/digiaddress/index.php

      . . .
                  <!-- add form code here -->
      . . .
      

      We'll add a few dozen lines of code below this comment which will create a form where users can enter the address of a physical location which the application will use to generate a mapcode. Under this comment, add the following highlighted code which creates a title called Enter Address at the top of the form:

      /var/www/html/digiaddress/index.php

      . . .
                  <!-- add form code here -->
      
                  <div class="form-border spacing-top">
                      <div class="card-header" style="background:#cc0001; color:#ffff">
                          <h5>Enter Address</h5>
                      </div>
                      <div class="extra-padding">
      . . .
      

      Below this, add the following HTML code. This creates a form with five text fields (along with their appropriate labels) where users will input their information:

      /var/www/html/digiaddress/index.php

                      . . .
                      <form>
                              <div class="form-group input-group-sm">
                                  <label for="state">State</label>
                                  <input type="text" class="form-control rounded-0 textbox-border" id="state"
                                         placeholder="" ng-model="address.state"/>
                              </div>
                              <div class="form-group input-group-sm">
                                  <label for="zip" class="animated-label">Zip</label>
                                  <input type="text" class="form-control rounded-0 textbox-depth textbox-border"
                                         id="zip" ng-model="address.zip" disabled="disabled"/>
                              </div>
                              <div class="form-group input-group-sm">
                                  <label for="town">Town</label>
                                  <input type="text" class="form-control rounded-0 textbox-border"
                                         id="town" ng-model="address.town" disabled="disabled"/>
                              </div>
                              <div class="form-group input-group-sm">
                                  <label for="street">Street</label>
                                  <input type="text" class="form-control rounded-0 textbox-border" id="street"
                                         placeholder="" ng-model="address.street" disabled="disabled"/>
                              </div>
                              <div class="form-group input-group-sm">
                                  <label for="house">House</label>
                                  <input type="text" class="form-control rounded-0 textbox-border" id="house"
                                         placeholder="" ng-model="address.house" disabled="disabled"/>
                              </div>
                       . . .
      

      Below the form code, add the following lines. These create two hidden controls which pass along the latitude and longitude information derived from any address submitted through the form:

      /var/www/html/digiaddress/index.php

                                  . . .
                                  <div class="form-group input-group-sm">
                                      <input type="hidden" ng-model="address.lat"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <input type="hidden" ng-model="address.long"/>
                                  </div>
                                  . . .
      

      Lastly, close out this section by adding the following code. This creates a Generate button which will allow users to submit the form:

      /var/www/html/digiaddress/index.php

                                  . . .
                                  <button type="submit" disabled="disabled" class="btn btn-color btn-block rounded-0" id="generate"
                                          style="color:#ffff;background-color: #cc0001;">Generate
                                  </button>
                          </form>
                      </div>
                  </div>
              . . .
      

      After adding these elements, this section of the file should match this:

      /var/www/html/digiaddress/index.php

      . . .
                  <!-- add form code here -->
      
                  <div class="form-border spacing-top">
                      <div class="card-header" style="background:#cc0001; color:#ffff">
                          <h5>Enter Address</h5>
                      </div>
                      <div class="extra-padding">
                          <form>    
                                  <div class="form-group input-group-sm">
                                      <label for="state">State</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="state"
                                             placeholder="" ng-model="address.state"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="zip" class="animated-label">Zip</label>
                                      <input type="text" class="form-control rounded-0 textbox-depth textbox-border"
                                             id="zip" ng-model="address.zip" disabled="disabled"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="town">Town</label>
                                      <input type="text" class="form-control rounded-0 textbox-border "
                                             id="town" ng-model="address.town" disabled="disabled"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="street">Street</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="street"
                                             placeholder="" ng-model="address.street" disabled="disabled"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="house">House</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="house"
                                             placeholder="" ng-model="address.house" disabled="disabled"/>
                                  </div>
      
                                  <div class="form-group input-group-sm">
                                      <input type="hidden" ng-model="address.lat"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <input type="hidden" ng-model="address.long"/>
                                  </div>
                                  <button type="submit" disabled="disabled" class="btn btn-color btn-block rounded-0" id="generate"
                                          style="color:#ffff;background-color: #cc0001;">Generate
                                  </button>
                          </form>
                      </div>
                  </div>
                  <br>
              </div>
      
              <!-- add google map control -->
                          . . .
      

      Save the file by pressing CTRL+O then ENTER, and then visit the application in your browser again:

      http://your_server_ip/digiaddress
      

      You will see the newly-added form fields and Generate button, and the application should look like this:

      At this point, if you enter address information into the form and try clicking the Generate button, nothing will happen. We will add the mapcode generation functionality later on, but let's first focus on making this page more visually engaging by adding a map which users can interact with.

      Step 5 — Adding Google Maps Controls

      When maps are displayed on a website through the Google Maps JavaScript API, they contain user interface features that allow visitors to interact with the map they see. These features are known as controls. We will continue editing the index.php file to add Google Maps controls to this app and, when finished, users will be able to view a map next to the input form, drag it around to view different locations, zoom in and out, and switch between Google's map, satellite, and street views.

      Find the following comment within the index.php file:

      /var/www/html/digiaddress/index.php

      . . .
      <!-- add google map control -->
      . . .
      

      Add the following highlighted code below this comment:

      /var/www/html/digiaddress/index.php

      . . .
              <!-- add google map control -->
      
              <div class="col-sm-8 map-align" ng-init="initMap()">
                  <div id="map" class="extra-padding" style="height: 100%;
                  margin-bottom: 15px;"></div>
                  <label id="geocoordinates" ng-show="latlng" ng-model="lt"></label><br/>
                  <label id="geoaddress" ng-show="address" ng-model="padd"></label>
                  </div>
              </div>
      . . .
      

      Save the file, then visit the application in your browser again. You will see the following:

      As you can see, we've successfully added a map to the application. You can drag the map around to focus on different locations, zoom in and out, and switch between the map, satellite, and street views. Looking back at the code you just added, notice that we've also added two label controls that will display the geocoordinates and the physical address that were entered on the form:

      /var/www/html/digiaddress/index.php

                  . . .
                  <label id="geocoordinates" ng-show="latlng" ng-model="lt"></label><br/>
                  <label id="geoaddress" ng-show="address" ng-model="padd"></label>
                  . . .
      

      Visit the application again in your browser and enter the name of a state in the first field. When you move your text cursor to the next field, the latitude and longitude labels don't appear, nor does the location shown on the map change to reflect the information you've entered. Let's enable these behaviors.

      Step 6 — Adding Event Listeners

      Adding interactive elements to an application can help to keep its users engaged. We will implement a few interactive behaviors in this application through the use of event listeners.

      An event is any action that takes place on a web page. Events can be something done by a user or by the browser itself. Examples of common events are:

      • Clicking an HTML button
      • Changing the content of an input field
      • Changing the focus from one page element to another

      An event listener is a directive that tells a program to take a certain action when a specific event takes place. In AngularJS, event listeners are defined with directives that generally follow this format:

      ng-event_type=expression
      

      In this step, we will add an event listener that helps to process the information entered by users into a mapcode whenever they submit the form. We will also add a couple more event listeners that will make the application more interactive. Specifically, we'll use these listeners to change the location shown in the application map, place a marker, and draw a rectangle around the location as users enter information into the form. We'll add these event listeners to index.php, so open that file up again if you've closed it:

      • nano /var/www/html/digiaddress/index.php

      Scroll down to the first batch of code we added, and find the block that begins with <form>. It will look like this:

      /var/www/html/digiaddress/index.php

                      . . .
                          <form>
                                  <div class="form-group input-group-sm">
                                      <label for="state">State</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="state"
                                             placeholder="" ng-model="address.state"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="zip" class="animated-label">Zip</label>
                                      <input type="text" class="form-control rounded-0 textbox-depth textbox-border"
                                             id="zip" ng-model="address.zip" disabled="disabled"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="town">Town</label>
                                      <input type="text" class="form-control rounded-0 textbox-border"
                                             id="town" ng-model="address.town" disabled="disabled"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="street">Street</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="street"
                                             placeholder="" ng-model="address.street" disabled="disabled"/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="house">House</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="house"
                                             placeholder="" ng-model="address.house" disabled="disabled"/>
                                  </div>
                          </form>
      . . .
      

      To begin, add the following highlighted event listener to the opening <form> tag. This code tells the app to call the processForm function whenever a user submits information through the form. processForm is defined in the createDigitalAddressApp.js file, and serves as a helper function that sends the information submitted by users to the appropriate files which then process it into a mapcode. We will take a closer look at this function in Step 7:

      /var/www/html/digiaddress/index.php

                      . . .
                          <form ng-submit="processForm()" class="custom-form">
                                  <div class="form-group input-group-sm">
                                      <label for="state">State</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="state"
                                             placeholder="" ng-model="address.state"
                                  </div>
                      . . .
      

      Next, continue editing this block by adding a couple blur event listeners. A blur event occurs when a given page element loses focus. Add the following highlighted lines to the form block's input tags. These lines tell the application to call the geocodeAddress function when a user's focus shifts away from the respective form fields we created in Step 4. Note that you must also delete the slashes and greater-than signs (/>) that close out each input tag. Failing to do so will prevent the app from registering the blur events correctly:

      /var/www/html/digiaddress/index.php

                      . . .
                      <form ng-submit="processForm()" class="custom-form">
                                  <div class="form-group input-group-sm">
                                      <label for="state">State</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="state"
                                             placeholder="" ng-model="address.state"
                                             ng-blur="geocodeAddress(address,'state')" required=""/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="zip" class="animated-label">Zip</label>
                                      <input type="text" class="form-control rounded-0 textbox-depth textbox-border"
                                             id="zip" ng-model="address.zip" disabled="disabled"
                                             ng-blur="geocodeAddress(address,'zip')" required=""/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="town">Town</label>
                                      <input type="text" class="form-control rounded-0 textbox-border"
                                             id="town" ng-model="address.town" disabled="disabled"
                                             ng-blur="geocodeAddress(address,'town')" required=""/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="street">Street</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="street"
                                             placeholder="" ng-model="address.street" disabled="disabled"
                                             ng-blur="geocodeAddress(address,'street')" required=""/>
                                  </div>
                                  <div class="form-group input-group-sm">
                                      <label for="house">House</label>
                                      <input type="text" class="form-control rounded-0 textbox-border" id="house"
                                             placeholder="" ng-model="address.house" disabled="disabled"
                                             ng-blur="geocodeAddress(address,'house')" required=""/>
                                  </div>
      . . .
      

      The first of these new lines — ng-blur="geocodeAddress(address,'state')" required=""/> — translates to "When the user's focus shifts away from the 'state' field, call the geocodeAddress function." The other new lines also call geocodeAddress, albeit when the user's focus shifts away from their respective fields.

      As with the processForm function, geocodeAddress is declared in the createDigitalAddressApp.js file, but there isn't yet any code in that file that defines it. We will complete this function so that it places a marker and draws a rectangle on the application map after these blur events occur to reflect the information entered into the form. We'll also add some code that takes the address information and processes it into a mapcode.

      Save and close the index.php file (press CTRL+X, Y, then ENTER) and then open thecreateDigitalAddressApp.js file:

      • nano /var/www/html/digiaddress/js/createDigitalAddressApp.js

      In this file, find the following line:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      . . .
      $scope.geocodeAddress = function (address, field) {
      . . .
      

      This line is where we declare the geocodeAddress function. A few lines below this, we declare a variable named fullAddress which constructs a human-readable mailing address from the information entered by a user into the application's form fields. This is done through a series of if statements:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      . . .
      var fullAddress = "";
      
          if (address ['house']) {
              angular.element(document.getElementById('generate'))[0].disabled = false;
                  fullAddress = address ['house'] + ",";
                      }
          if (address ['town']) {
              angular.element(document.getElementById('street'))[0].disabled = false;
                  fullAddress = fullAddress + address ['town'] + ",";
          }
          if (address ['street']) {
              angular.element(document.getElementById('house'))[0].disabled = false;
                  fullAddress = fullAddress + address ['street'] + ",";
          }
          if (address ['state']) {
              angular.element(document.getElementById('zip'))[0].disabled = false;
                  fullAddress = fullAddress + address ['state'] + " ";
          }
          if (address ['zip']) {
              angular.element(document.getElementById('town'))[0].disabled = false;
                  fullAddress = fullAddress + address ['zip'];
          }
      . . .
      

      Directly after these lines is the following comment:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      . . .
      // add code for locating the address on Google maps
      . . .
      

      Underneath this comment, add the following line which checks whether fullAddress is any value other than null:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                      . . .
                      if (fullAddress !== "") {
                      . . .
      

      Add the following code below this line. This code submits the information entered into the form to the geoimplement.php file using the HTTP POST method if fullAddress is not null:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                          . . .
                          $http({
                              method: 'POST',
                              url: 'geoimplement.php',
                              data: {address: fullAddress},
                              headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      
                          }).then(function successCallback(results) {
                          . . .
      

      Next, add the following line which checks whether the PHP call was returned successfully:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                              . . .
                              if (results.data !== "false") {
                              . . .
      

      If the PHP call was successfully returned, we'll be able to process the result. Add the following line, which removes any boundary rectangle that may have been previously drawn on the map by calling the removeRectangle function, which is defined at the top of the createDigitalAddressApp.js file:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                                  . . .
                                  removeRectangle();
                                  . . .
      

      Under the removeRectangle(); line, add the following four lines which will create a marker pointing to the new location on the map control:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                                  . . .
                                  new google.maps.Marker({
                                      map: locationMap,
                                      position: results.data.geometry.location
                                  });
                                  . . .
      

      Then add the following code, which obtains the latitude and longitude information from the result and displays it with the two HTML labels we created in the index.php file in Step 5:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                                  . . .
                                  lat = results.data.geometry.location.lat;
                                  lng = results.data.geometry.location.lng;
      
                                  $scope.address.lat = lat;
                                  $scope.address.lng = lng;
      
                                  geoCoordLabel = angular.element(document.querySelector('#geocoordinates'));
                                  geoCoordLabel.html("Geo Coordinate: " + lat + "," + lng);
      
                                  geoAddressLabel = angular.element(document.querySelector('#geoaddress'));
                                  geoAddressLabel.html("Geo Address: " + fullAddress);
      
                                  $scope.latlng = true;
                                  . . .
      

      Lastly, below these lines, add the following content. This code creates a viewport which marks a new boundary rectangle on the map:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                                  . . .
                                  if (results.data.geometry.viewport) {
      
                                      rectangle = new google.maps.Rectangle({
                                          strokeColor: '#FF0000',
                                          strokeOpacity: 0.8,
                                          strokeWeight: 0.5,
                                          fillColor: '#FF0000',
                                          fillOpacity: 0.35,
                                          map: locationMap,
                                          bounds: {
                                              north: results.data.geometry.viewport.northeast.lat,
                                              south: results.data.geometry.viewport.southwest.lat,
                                              east: results.data.geometry.viewport.northeast.lng,
                                              west: results.data.geometry.viewport.southwest.lng
                                          }
                                      });
      
                                      var googleBounds = new google.maps.LatLngBounds(results.data.geometry.viewport.southwest, results.data.geometry.viewport.northeast);
      
                                      locationMap.setCenter(new google.maps.LatLng(lat, lng));
                                      locationMap.fitBounds(googleBounds);
                                  }
                              } else {
                                  errorLabel = angular.element(document.querySelector('#lt'));
                                  errorLabel.html("Place not found.");
                                  $scope.latlng = true;
                                  removeRectangle();
                              }
      
                          }, function errorCallback(results) {
                             console.log(results);
                          });
                      }
                      . . .
      

      After adding this content, this section of the file will look like this:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

                      . . .
                      // add code for locating the address on Google maps
                      if (fullAddress !== "") {
                          $http({
                              method: 'POST',
                              url: 'geoimplement.php',
                              data: {address: fullAddress},
                              headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      
                          }).then(function successCallback(results) {
      
                              if (results.data !== "false") {
                                  removeRectangle();
      
                                  new google.maps.Marker({
                                      map: locationMap,
                                      position: results.data.geometry.location
                                  });
      
                                  lat = results.data.geometry.location.lat;
                                  lng = results.data.geometry.location.lng;
      
                                  $scope.address.lat = lat;
                                  $scope.address.lng = lng;
      
                                  geoCoordLabel = angular.element(document.querySelector('#geocoordinates'));
                                  geoCoordLabel.html("Geo Coordinate: " + lat + "," + lng);
      
                                  geoAddressLabel = angular.element(document.querySelector('#geoaddress'));
                                  geoAddressLabel.html("Geo Address: " + fullAddress);
      
                                  $scope.latlng = true;
      
                                  if (results.data.geometry.viewport) {
      
                                      rectangle = new google.maps.Rectangle({
                                          strokeColor: '#FF0000',
                                          strokeOpacity: 0.8,
                                          strokeWeight: 0.5,
                                          fillColor: '#FF0000',
                                          fillOpacity: 0.35,
                                          map: locationMap,
                                          bounds: {
                                              north: results.data.geometry.viewport.northeast.lat,
                                              south: results.data.geometry.viewport.southwest.lat,
                                              east: results.data.geometry.viewport.northeast.lng,
                                              west: results.data.geometry.viewport.southwest.lng
                                          }
                                      });
      
                                      var googleBounds = new google.maps.LatLngBounds(results.data.geometry.viewport.southwest, results.data.geometry.viewport.northeast);
      
                                      locationMap.setCenter(new google.maps.LatLng(lat, lng));
                                      locationMap.fitBounds(googleBounds);
                                  }
                              } else {
                                  errorLabel = angular.element(document.querySelector('#lt'));
                                  errorLabel.html("Place not found.");
                                  $scope.latlng = true;
                                  removeRectangle();
                              }
      
                          }, function errorCallback(results) {
                             console.log(results);
                          });
                      }
                      . . .
      

      Save the file, but keep it open for now. If you were to visit the application in your browser again, you wouldn't see any new changes to its appearance or behavior. Likewise, if you were to enter an address and click on the Generate button, the application still would not generate or display a mapcode. This is because we must still edit a few files before the mapcode functionality will work. Let's continue to make these changes, and also take a closer look at how these mapcodes are generated.

      Step 7 — Understanding Mapcode Generation

      While still looking at the createDigitalAddressApp.js file, scroll past the section of code that you added in the previous step to find the code that takes the information submitted through the form and process it into a unique mapcode. Whenever a user clicks the Generate button, the code within the index.php file submits the form and calls the processForm function, which is defined here in createDigitalAddressApp.js:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      . . .
      $scope.processForm = function () {
      . . .
      

      processForm then makes an HTTP POST to the generateDigitalAddress.php file:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      . . .
      $http({
          method: 'POST',
          url: 'generateDigitalAddress.php',
          data: $scope.address,
          headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      }).then(function (response) {
      . . .
      

      The Stichting Mapcode Foundation provides the API that generates mapcodes from physical addresses as a free web service. To understand how this call to the Mapcode web service works, close createDigitalAddressApp.js and open the generateDigitialAddress.php file:

      • nano /var/www/html/digiaddress/generateDigitalAddress.php

      At the top of the file, you'll see the following:

      /var/www/html/digiaddress/generateDigitalAddress.php

      <?php
      include("db.php");
      . . .
      

      The line reading include("db.php"); tells PHP to include all the text, code, and markup from the db.php file within the generateDigitalAddress.php file. db.php holds the login credentials for the MySQL database you created in Step 2, and by including it within generateDigitalAddress.php, we can add any address information submitted through the form to the database.

      Below this include statement are a few more lines that obtain the latitude and longitude information based on the request submitted by createDigitalAddressApp.js:

      /var/www/html/digiaddress/generateDigitalAddress.php

      . . .
      $data = json_decode(file_get_contents("php://input"));
      $lat = $data->lat;
      $long = $data->lng;
      . . .
      

      Look for the following comment in generateDigitalAddress.php file.

      /var/www/html/digiaddress/generateDigitalAddress.php

      . . .
      // call to mapcode web service
      . . .
      

      Add the following line of code below this comment. This code makes a call the Mapcode API, sending lat and long as parameters.

      /var/www/html/digiaddress/generateDigitalAddress.php

      . . .
      // call to mapcode web service
      $digitaldata = file_get_contents("https://api.mapcode.com/mapcode/codes/".$lat.",".$long."?include=territory,alphabet&allowLog=true&client=web");
      . . .
      

      The web service returns the JSON data which was assigned to digitaldata, and the following statement decodes that JSON:

      /var/www/html/digiaddress/generateDigitalAddress.php

      . . .
      $digitalAddress["status"] = json_decode($digitaldata, TRUE)['local']['territory']." ".json_decode($digitaldata, TRUE)['local']['mapcode'];
      . . .
      

      This returns a mapcode for the user-specified location. The following lines then store this information in the database:

      /var/www/html/digiaddress/generateDigitalAddress.php

      . . .
      $obj = new databaseConnection();
      
      $conn = $obj->dbConnect();
      
      $obj->insertLocation($conn, $digitalAddress["status"],$data->state,$data->zip,$data->street,$data->town,$data->house,$lat,$long);
      . . .
      

      Then, the final line echoes the mapcode back to the caller function:

      /var/www/html/digiaddress/generateDigitalAddress.php

      . . .
      echo json_encode($digitalAddress);
      

      Save and close this file, then reopen createDigitalAddressApp.js again:

      • nano /var/www/html/digiaddress/js/createDigitalAddressApp.js

      When a mapcode has been retrieved successfully, the following lines in the createDigitalAddressApp.js file displays it to the user in a dialog box:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      . . .
      digiAddress = response.data.status;
      . . .
      $('#digitalAddressDialog').modal('show');
      . . .
      

      Although you did add a new line of code to generateDigitalAddress.php, you still won't see any functional changes when you visit and interact with the app in your browser. This is because you've not yet added your Google API key to the geoimplement.php file, which makes the actual call to the Google Maps API.

      Step 8 — Enabling Calls to the Google Maps API

      This application depends on the Google Maps API to translate a physical address into the appropriate latitude and longitude coordinates. These are then passed on to the Mapcode API which uses them to generate a mapcode. Consequently, if the application is unable to communicate with the Google Maps API to generate the location's latitude and longitude, any attempt to generate a mapcode will fail.

      Recall from Step 6 where, after constructing the address data, we passed the result along via an HTTP POST request in the createDigitalAddressApp.js file:

      /var/www/html/digiaddress/js/createDigitalAddressApp.js

      $http({
          method: 'POST',
          url: 'geoimplement.php',
          data: {address: fullAddress},
          headers: {'Content-Type': 'application/x-www-form-urlencoded'}
      }).then(function successCallback(results) {
      

      This code block sends the address data entered by a user to the geoimplement.php file which contains the code that calls the Google Maps API. Go ahead and open this file:

      • nano /var/www/html/digiaddress/geoimplement.php

      You'll see that it first decodes the address that was received through the POST request:

      /var/www/html/digiaddress/geoimplement.php

      . . .
      $data=json_decode(file_get_contents("php://input"));
      . . .
      

      It then passes the address field of the input data to a geocode function which returns the geographic information on the address:

      /var/www/html/digiaddress/geoimplement.php

      . . .
      $result = geocode($data->address);
      . . .
      

      The result is then echoed back to the caller:

      /var/www/html/digiaddress/geoimplement.php

      . . .
      echo json_encode($result);
      . . .
      

      The geocode function encodes the address and passes it on to the Google Maps API, along with your application key:

      /var/www/html/digiaddress/geoimplement.php

      . . .
      // url encode the address
      $address = urlencode($address);
      
      // google map geocode api url
      $url = "https://maps.googleapis.com/maps/api/geocode/json?address={$address}&key=<YOUR KEY>";
      . . .
      

      Before scrolling on, go ahead and add your API key to the line under the // google map geocode api url comment:

      /var/www/html/digiaddress/geoimplement.php

      . . .
      // google map geocode api url
      $url = "https://maps.googleapis.com/maps/api/geocode/json?address={$address}&key=ExampleAPIKeyH2vITfv1eIHbfka9ym634Esw7u";
      . . .
      

      After sending the call to the Google Maps API, the response is decoded and its value is returned by the function:

      /var/www/html/digiaddress/geoimplement.php

      . . .
      // get the json response
      $resp_json = file_get_contents($url);
      
      // decode the json
      $resp = json_decode($resp_json, true);
      
      if ($resp['status'] == 'OK') {
          return $resp['results'][0];
      } else {
          return false;
      }
      . . .
      

      Save this file, and visit your application once again. Input US-NY in the state field and then hit TAB to change the input focus to the next field. You will see the following output:

      Notice that the geocoordinates and physical address that you entered in the form appear underneath the map. This makes the application feel much more engaging and interactive.

      Note: When it comes to abbreviations for place names, Mapcode uses the ISO 3166 standard. This means that it may not interpret some commonly-used abbreviations as expected. For example, if you'd like to generate a Mapcode for an address in Louisiana and you enter LA, the map will jump to Los Angeles, California (rather than the state of Louisiana).

      You can avoid confusion with US postal abbreviations by preceding them with US-. In the context of this Louisiana example, you would enter US-LA.

      To learn more about how Mapcode uses this standard, check out the Territories and standard codes reference page.

      Despite this improvement to how the application displays locations on the map, the app still isn't fully functional. The last step you need to take before you can generate a mapcode is to edit the db.php file to allow the application to access your database.

      Step 9 — Adding Database Credentials and Testing Mapcode Generation

      Recall that this application stores every address entered into the form — along with its latitude, longitude, and mapcode — in the database you created in Step 2. This is made possible by the code within the db.php file, which stores your database credentials and allows the application to access the locations table within it.

      As a final step to enable the mapcode generation functionality, open the db.php file for editing:

      • nano /var/www/html/digiaddress/db.php

      Near the top of this file, find the line that begins with $pass. This line submits your MySQL login credentials in order to allow the application to access your database. Replace your_password with your root MySQL user's password:

      /var/www/html/digiaddress/db.php

      . . .
              $username = "root";
              $pass = "your_password";
      . . .
      

      That is the last change you need to make in order to generate a mapcode from a physical address. Save and close the file, then go ahead and refresh the application in your browser once again. Enter in an address of your choice and click the Generate button. The output will look similar to this:

      At this stage, you have completed your application and you can now generate a short digital address for any physical location in the world. Feel free to experiment with different addresses, and note that the address you enter does not necessarily need to be within the United States.

      Your final task is to enable this app's second functionality: retrieving an address from the database using its respective mapcode.

      Step 10 — Retrieving a Physical Address

      Now that you're able to generate a mapcode from a given physical address, your final step is to retrieve the original physical address, as derived from the mapcode. To accomplish this, we will develop a PHP user interface, shown here:

      The code for this UI is available in the findaddress.php file. As the UI defined within this file is fairly similar to the UI we covered earlier in Step 4, we will not look too closely at all the details of how it works. We will, however, go through these three files to explain generally how they function.

      In order to enable the address retrieval functionality, you'll need to add your Google API key to the findaddress.php file, so open it up with your preferred editor:

      • nano /var/www/html/digiaddress/findaddress.php

      Near the bottom of the file, find the line that begins with <script async defer src=. It will look like this:

      /var/www/html/digiaddress/findaddress.php

      <script async defer src="https://maps.googleapis.com/maps/api/js?key=<YOUR KEY>"></script>
      

      Replace <YOUR KEY> with your Google API key as you've done in the previous steps, then save the file. Before closing it, though, let's take a quick look to see how these files work together.

      When a user submits the form it triggers a submit event, and an event listener calls the fetchadd function:

      /var/www/html/digiaddress/findaddress.php

      . . .
      <form ng-submit="fetchadd()" class="custom-form">
      . . .
      

      The fetchadd function sends the digital address to fetchaddress.php with a POST request:

      /var/www/html/digiaddress/js/findAddressApp.js

      . . .
      $http({
          method : 'POST',
          url : 'fetchaddress.php',
          data : {digiaddress: $scope.digiaddress}
      }).then(function(response){
      . . .
      

      If the POST is successful, the function returns a JSON response. The following line parses this response:

      /var/www/html/digiaddress/js/findAddressApp.js

      . . .
      var jsonlatlng = JSON.parse(response.data.latlng);
      . . .
      

      The next lines set the marker on the map:

      /var/www/html/digiaddress/js/findAddressApp.js

      . . .
      marker = new google.maps.Marker({
          position: new google.maps.LatLng(jsonlatlng.latitude, jsonlatlng.longitude),
              map: locationMap
      });
      . . .
      

      And the following prints the geocoordinates and the physical address:

      /var/www/html/digiaddress/js/findAddressApp.js

      . . .
      geoCoordLabel = angular.element(document.querySelector('#geocoordinates'));
      geoCoordLabel.html("Geo Coordinate: "+ jsonlatlng.latitude +","+ jsonlatlng.longitude);
      
      geoAddressLabel = angular.element(document.querySelector('#geoaddress'));
      geoAddressLabel.html("Geo Address: " + jsonlatlng.house +","+ jsonlatlng.town +","+ jsonlatlng.street +","+ jsonlatlng.state + " " + jsonlatlng.zip );
      . . .
      

      Visit this application in your browser by going to the following link:

      http://your_server_ip/digiaddress/findaddress.php
      

      Test it out by entering in the mapcode you obtained earlier. The following figure shows a typical output:

      With that, your application is finished. You can now create a unique mapcode for any location in the world, and then use that mapcode to retrieve the location's physical address.

      Conclusion

      In this tutorial you used the Google Maps API to pin a location and gets its longitude, latitude information. This information is used to generate a unique and short digital address using Mapcode API. There are a number of practical use cases for mapcodes, ranging from emergency services to archaeological surveying. The Stichting Mapcode Foundation lists several such use cases.

      Acknowledgements

      Many thanks to Dinesh Karpe and Sayli Patil for developing the entire project code.



      Source link

      How To Install Linux, Apache, MariaDB, PHP (LAMP) stack on Debian 9


      Introduction

      A “LAMP” stack is a group of open source software that is typically installed together to enable a server to host dynamic websites and web apps. This term is actually an acronym which represents the Linux operating system, with the Apache web server. The site data is stored in a MariaDB database, and dynamic content is processed by PHP.

      In this guide, we will install a LAMP stack on a Debian 9 server.

      Prerequisites

      In order to complete this tutorial, you will need to have a Debian 9 server with a non-root sudo-enabled user account and a basic firewall. This can be configured using our initial server setup guide for Debian 9.

      Step 1 — Installing Apache and Updating the Firewall

      The Apache web server is among the most popular web servers in the world. It’s well-documented and has been in wide use for much of the history of the web, which makes it a great default choice for hosting a website.

      Install Apache using Debian’s package manager, apt:

      • sudo apt update
      • sudo apt install apache2

      Since this is a sudo command, these operations are executed with root privileges. It will ask you for your regular user’s password to verify your intentions.

      Once you’ve entered your password, apt will tell you which packages it plans to install and how much extra disk space they’ll take up. Press Y and hit ENTER to continue, and the installation will proceed.

      Next, assuming that you have followed the initial server setup instructions by installing and enabling the UFW firewall, make sure that your firewall allows HTTP and HTTPS traffic.

      When installed on Debian 9, UFW comes loaded with app profiles which you can use to tweak your firewall settings. View the full list of application profiles by running:

      The WWW profiles are used to manage ports used by web servers:

      Output

      Available applications: . . . WWW WWW Cache WWW Full WWW Secure . . .

      If you inspect the WWW Full profile, it shows that it enables traffic to ports 80 and 443:

      • sudo ufw app info "WWW Full"

      Output

      Profile: WWW Full Title: Web Server (HTTP,HTTPS) Description: Web Server (HTTP,HTTPS) Ports: 80,443/tcp

      Allow incoming HTTP and HTTPS traffic for this profile:

      • sudo ufw allow in “WWW Full”

      You can do a spot check right away to verify that everything went as planned by visiting your server's public IP address in your web browser:

      http://your_server_ip
      

      You will see the default Debian 9 Apache web page, which is there for informational and testing purposes. It should look something like this:

      Debian 9 Apache default

      If you see this page, then your web server is now correctly installed and accessible through your firewall.

      If you do not know what your server's public IP address is, there are a number of ways you can find it. Usually, this is the address you use to connect to your server through SSH.

      There are a few different ways to do this from the command line. First, you could use the iproute2 tools to get your IP address by typing this:

      • ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's//.*$//'

      This will give you two or three lines back. They are all correct addresses, but your computer may only be able to use one of them, so feel free to try each one.

      An alternative method is to use the curl utility to contact an outside party to tell you how it sees your server. This is done by asking a specific server what your IP address is:

      • sudo apt install curl
      • curl http://icanhazip.com

      Regardless of the method you use to get your IP address, type it into your web browser's address bar to view the default Apache page.

      Step 2 — Installing MariaDB

      Now that you have your web server up and running, it is time to install MariaDB. MariaDB is a database management system. Basically, it will organize and provide access to databases where your site can store information.

      MariaDB is a community-built fork of MySQL. In Debian 9, the default MySQL server is MariaDB 10.1, and the mysql-server package, which is normally used to install MySQL, is a transitional package that will actually install MariaDB. However, it’s recommended that you install MariaDB using the program’s actual package, mariadb-server.

      Again, use apt to acquire and install this software:

      • sudo apt install mariadb-server

      Note: In this case, you do not have to run sudo apt update prior to the command. This is because you recently ran it in the commands above to install Apache, and the package index on your computer should already be up-to-date.

      This command, too, will show you a list of the packages that will be installed, along with the amount of disk space they'll take up. Enter Y to continue.

      When the installation is complete, run a simple security script that comes pre-installed with MariaDB which will remove some insecure default settings and lock down access to your database system. Start the interactive script by running:

      • sudo mysql_secure_installation

      This will take you through a series of prompts where you can make some changes to your MariaDB installation’s security options. The first prompt will ask you to enter the current database root password. This is an administrative account in MariaDB that has increased privileges. Think of it as being similar to the root account for the server itself (although the one you are configuring now is a MariaDB-specific account). Because you just installed MariaDB and haven’t made any configuration changes yet, this password will be blank, so just press ENTER at the prompt.

      The next prompt asks you whether you'd like to set up a database root password. Type N and then press ENTER. In Debian, the root account for MariaDB is tied closely to automated system maintenance, so we should not change the configured authentication methods for that account. Doing so would make it possible for a package update to break the database system by removing access to the administrative account. Later, we will cover how to optionally set up an additional administrative account for password access if socket authentication is not appropriate for your use case.

      From there, you can press Y and then ENTER to accept the defaults for all the subsequent questions. This will remove some anonymous users and the test database, disable remote root logins, and load these new rules so that MariaDB immediately respects the changes you have made.

      In new installs on Debian systems, the root MariaDB user is set to authenticate using the unix_socket plugin by default rather than with a password. This allows for some greater security and usability in many cases, but it can also complicate things when you need to allow an external program (e.g., phpMyAdmin) administrative rights.

      Because the server uses the root account for tasks like log rotation and starting and stopping the server, it is best not to change the root account's authentication details. Changing the account credentials in the /etc/mysql/debian.cnf may work initially, but package updates could potentially overwrite those changes. Instead of modifying the root account, the package maintainers recommend creating a separate administrative account if you need to set up password-based access.

      To do so, we will be creating a new account called admin with the same capabilities as the root account, but configured for password authentication. To do this, open up the MariaDB prompt from your terminal:

      Now, we can create a new user with root privileges and password-based access. Change the username and password to match your preferences:

      • GRANT ALL ON *.* TO 'admin'@'localhost' IDENTIFIED BY 'password' WITH GRANT OPTION;

      Flush the privileges to ensure that they are saved and available in the current session:

      Following this, exit the MariaDB shell:

      Now, any time you want to access your database as your new administrative user, you’ll need to authenticate as that user with the password you just set using the following command:

      At this point, your database system is set up and you can move on to installing PHP, the final component of the LAMP stack.

      Step 3 — Installing PHP

      PHP is the component of your setup that will process code to display dynamic content. It can run scripts, connect to your MariaDB databases to get information, and hand the processed content over to your web server to display.

      Once again, leverage the apt system to install PHP. In addition, include some helper packages this time so that PHP code can run under the Apache server and talk to your MariaDB database:

      • sudo apt install php libapache2-mod-php php-mysql

      This should install PHP without any problems. We'll test this in a moment.

      In most cases, you will want to modify the way that Apache serves files when a directory is requested. Currently, if a user requests a directory from the server, Apache will first look for a file called index.html. We want to tell the web server to prefer PHP files over others, so make Apache look for an index.php file first.

      To do this, type this command to open the dir.conf file in a text editor with root privileges:

      • sudo nano /etc/apache2/mods-enabled/dir.conf

      It will look like this:

      /etc/apache2/mods-enabled/dir.conf

      <IfModule mod_dir.c>
          DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm
      </IfModule>
      

      Move the PHP index file (highlighted above) to the first position after the DirectoryIndex specification, like this:

      /etc/apache2/mods-enabled/dir.conf

      <IfModule mod_dir.c>
          DirectoryIndex index.php index.html index.cgi index.pl index.xhtml index.htm
      </IfModule>
      

      When you are finished, save and close the file by pressing CTRL+X. Confirm the save by typing Y and then hit ENTER to verify the file save location.

      After this, restart the Apache web server in order for your changes to be recognized. Do this by typing this:

      • sudo systemctl restart apache2

      You can also check on the status of the apache2 service using systemctl:

      • sudo systemctl status apache2

      Sample Output

      ● apache2.service - The Apache HTTP Server Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2018-09-04 18:23:03 UTC; 9s ago Process: 22209 ExecStop=/usr/sbin/apachectl stop (code=exited, status=0/SUCCESS) Process: 22216 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS) Main PID: 22221 (apache2) Tasks: 6 (limit: 4915) CGroup: /system.slice/apache2.service ├─22221 /usr/sbin/apache2 -k start ├─22222 /usr/sbin/apache2 -k start ├─22223 /usr/sbin/apache2 -k start ├─22224 /usr/sbin/apache2 -k start ├─22225 /usr/sbin/apache2 -k start └─22226 /usr/sbin/apache2 -k start

      To enhance the functionality of PHP, you have the option to install some additional modules. To see the available options for PHP modules and libraries, pipe the results of apt search into less, a pager which lets you scroll through the output of other commands:

      Use the arrow keys to scroll up and down, and press Q to quit.

      The results are all optional components that you can install. It will give you a short description for each:

      Output

      Sorting... Full Text Search... bandwidthd-pgsql/stable 2.0.1+cvs20090917-10 amd64 Tracks usage of TCP/IP and builds html files with graphs bluefish/stable 2.2.9-1+b1 amd64 advanced Gtk+ text editor for web and software development cacti/stable 0.8.8h+ds1-10 all web interface for graphing of monitoring systems cakephp-scripts/stable 2.8.5-1 all rapid application development framework for PHP (scripts) ganglia-webfrontend/stable 3.6.1-3 all cluster monitoring toolkit - web front-end haserl/stable 0.9.35-2+b1 amd64 CGI scripting program for embedded environments kdevelop-php-docs/stable 5.0.3-1 all transitional package for kdevelop-php kdevelop-php-docs-l10n/stable 5.0.3-1 all transitional package for kdevelop-php-l10n … :

      To learn more about what each module does, you could search the internet for more information about them. Alternatively, look at the long description of the package by typing:

      There will be a lot of output, with one field called Description which will have a longer explanation of the functionality that the module provides.

      For example, to find out what the php-cli module does, you could type this:

      Along with a large amount of other information, you'll find something that looks like this:

      Output

      … Description: command-line interpreter for the PHP scripting language (default) This package provides the /usr/bin/php command interpreter, useful for testing PHP scripts from a shell or performing general shell scripting tasks. . PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely-used open source general-purpose scripting language that is especially suited for web development and can be embedded into HTML. . This package is a dependency package, which depends on Debian's default PHP version (currently 7.0). …

      If, after researching, you decide you would like to install a package, you can do so by using the apt install command like you have been doing for the other software.

      If you decided that php-cli is something that you need, you could type:

      If you want to install more than one module, you can do that by listing each one, separated by a space, following the apt install command, like this:

      • sudo apt install package1 package2 ...

      At this point, your LAMP stack is installed and configured. Before making any more changes or deploying an application, though, it would be helpful to proactively test out your PHP configuration in case there are any issues that should be addressed.

      Step 4 — Testing PHP Processing on your Web Server

      In order to test that your system is configured properly for PHP, create a very basic PHP script called info.php. In order for Apache to find this file and serve it correctly, it must be saved to a very specific directory called the web root.

      In Debian 9, this directory is located at /var/www/html/. Create the file at that location by running:

      • sudo nano /var/www/html/info.php

      This will open a blank file. Add the following text, which is valid PHP code, inside the file:

      /var/www/html/info.php

      <?php
      phpinfo();
      ?>
      

      When you are finished, save and close the file.

      Now you can test whether your web server is able to correctly display content generated by this PHP script. To try this out, visit this page in your web browser. You'll need your server's public IP address again.

      The address you will want to visit is:

      http://your_server_ip/info.php
      

      The page that you come to should look something like this:

      Debian 9 default PHP info

      This page provides some basic information about your server from the perspective of PHP. It is useful for debugging and to ensure that your settings are being applied correctly.

      If you can see this page in your browser, then your PHP is working as expected.

      You probably want to remove this file after this test because it could actually give information about your server to unauthorized users. To do this, run the following command:

      • sudo rm /var/www/html/info.php

      You can always recreate this page if you need to access the information again later.

      Conclusion

      Now that you have a LAMP stack installed, you have many choices for what to do next. Basically, you've installed a platform that will allow you to install most kinds of websites and web software on your server.



      Source link

      How To Install Linux, Nginx, MySQL, PHP (LEMP stack) on Debian 9


      Introduction

      The LEMP software stack is a group of software that can be used to serve dynamic web pages and web applications. This is an acronym that describes a Linux operating system, with an Nginx web server. The backend data is stored in the MySQL database and the dynamic processing is handled by PHP.

      In this guide, you’ll install a LEMP stack on a Debian server using the packages provided by the operating system.

      Prerequisites

      To complete this guide, you will need a Debian 9 server with a non-root user with sudo privileges. You can set up a user with these privileges in our Initial Server Setup with Debian 9 guide.

      Step 1 — Installing the Nginx Web Server

      In order to display web pages to our site visitors, we are going to employ Nginx, a modern, efficient web server.

      All of the software we will be using for this procedure will come directly from Debian’s default package repositories. This means we can use the apt package management suite to complete the installation.

      Since this is our first time using apt for this session, we should start off by updating our local package index. We can then install the server:

      • sudo apt update
      • sudo apt install nginx

      On Debian 9, Nginx is configured to start running upon installation.

      If you have the ufw firewall running, you will need to allow connections to Nginx. You should enable the most restrictive profile that will still allow the traffic you want. Since we haven’t configured SSL for our server yet, in this guide, we will only need to allow traffic on port 80.

      You can enable this by typing:

      • sudo ufw allow 'Nginx HTTP'

      You can verify the change by typing:

      You should see HTTP traffic allowed in the displayed output:

      Output

      Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx HTTP ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx HTTP (v6) ALLOW Anywhere (v6)

      Now, test if the server is up and running by accessing your server's domain name or public IP address in your web browser. If you do not have a domain name pointed at your server and you do not know your server's public IP address, you can find it by typing one of the following into your terminal:

      • ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's//.*$//'

      This will print out a few IP addresses. You can try each of them in turn in your web browser.

      Type one of the addresses that you receive in your web browser. It should take you to Nginx's default landing page:

      http://your_domain_or_IP
      

      Nginx default page

      If you see the above page, you have successfully installed Nginx.

      Step 2 — Installing MySQL to Manage Site Data

      Now that we have a web server, we need to install MySQL, a database management system, to store and manage the data for our site.

      You can install this easily by typing:

      • sudo apt install mysql-server

      Note: In Debian 9 a community fork of the MySQL project – MariaDB – is packaged as the default MySQL variant. While, MariaDB works well in most cases, if you need features found only in Oracle's MySQL, you can install and use packages from a repository maintained by the MySQL developers. To install the official MySQL server, use our tutorial How To Install the Latest MySQL on Debian 9.

      The MySQL database software is now installed, but its configuration is not complete.

      To secure the installation, we can run a security script that will ask whether we want to modify some insecure defaults. Begin the script by typing:

      • sudo mysql_secure_installation

      You will be asked to enter the password for the MySQL root account. We haven't set this yet, so just hit ENTER. Then you'll be asked you if you want to set that password. You should type y then set a root password.

      For the rest of the questions the script asks, you should press y, followed by the ENTER key at each prompt. This will remove some anonymous users and the test database, disable remote root logins, and load these new rules so that MySQL immediately respects the changes you have made.

      At this point, your database system is now set up and secured. Let's set up PHP.

      Step 3 — Installing PHP for Processing

      We now have Nginx installed to serve our pages and MySQL installed to store and manage our data. However, we still don't have anything that can generate dynamic content. That's where PHP comes in.

      Since Nginx does not contain native PHP processing like some other web servers, we will need to install fpm, which stands for "fastCGI process manager". We will tell Nginx to pass PHP requests to this software for processing. We'll also install an additional helper package that will allow PHP to communicate with our MySQL database backend. The installation will pull in the necessary PHP core files to make that work.

      Then install the php-fpm and php-mysql packages:

      • sudo apt install php-fpm php-mysql

      We now have our PHP components installed. Next we'll configure Nginx to use them.

      Step 4 — Configuring Nginx to Use the PHP Processor

      Now we have all of the required components installed. The only configuration change we still need is to tell Nginx to use our PHP processor for dynamic content.

      We do this on the server block level (server blocks are similar to Apache's virtual hosts). We're going to leave the default Nginx configuration alone and instead create a new configuration file and new web root directory to hold our PHP files. We'll name the configuration file and the directory after the domain name or hostname that the server should respond to.

      First, create a new directory in /var/www to hold the PHP site:

      • sudo mkdir /var/www/your_domain

      Then, open a new configuration file in Nginx's sites-available directory:

      • sudo nano /etc/nginx/sites-available/your_domain

      This will create a new blank file. Paste in the following bare-bones configuration:

      /etc/nginx/sites-available/your_domain

      server {
          listen 80;
          listen [::]:80;
      
          root /var/www/your_domain;
          index index.php index.html index.htm;
      
          server_name your_domain;
      
          location / {
              try_files $uri $uri/ =404;
          }
      
          location ~ .php$ {
              include snippets/fastcgi-php.conf;
              fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
          }
      }
      

      This is a very basic configuration that listens on port 80 and serves files from the web root we just created. It will only respond to requests to the name provided after server_name, and any files ending in .php will be processed by the php-fpm process before Nginx sends the results to the user.

      Save and close the file when you're done customizing it.

      Activate your configuration by linking to the config file from Nginx's sites-enabled directory:

      • sudo ln -s /etc/nginx/sites-available/your_domain.conf /etc/nginx/sites-enabled/

      This will tell Nginx to use the configuration next time it is reloaded. First, test your configuration for syntax errors by typing:

      If any errors are reported, go back and recheck your file before continuing.

      When you are ready, reload Nginx to make the changes:

      • sudo systemctl reload nginx

      Next we'll create a file in our new web root directory to test out PHP processing.

      Step 5 — Create a PHP File to Test Configuration

      Your LEMP stack should now be completely set up. We can test it to validate that Nginx can correctly hand .php files off to our PHP processor.

      We can do this by creating a test PHP file in our document root. Open a new file called info.php within your document root in your text editor:

      • sudo nano /var/www/your_domain/info.php

      Type or paste the following lines into the new file. This is valid PHP code that will return information about our server:

      /var/www/your_domain/info.php

      <?php
        phpinfo();
      ?>
      

      When you are finished, save and close the file.

      Now, you can visit this page in your web browser by visiting your server's domain name or public IP address followed by /info.php:

      http://your_domain/info.php
      

      You should see a web page that has been generated by PHP with information about your server:

      PHP page info

      If you see a page that looks like this, you've set up PHP processing with Nginx successfully.

      After verifying that Nginx renders the page correctly, it's best to remove the file you created as it can actually give unauthorized users some hints about your configuration that may help them try to break in.

      For now, remove the file by typing:

      • sudo rm /var/www/html/info.php

      You can always regenerate this file if you need it later.

      Conclusion

      You should now have a LEMP stack configured on your Debian server. This gives you a very flexible foundation for serving web content to your visitors.



      Source link