2

I've been working on a 3-tier architecture and would like some reassurance that my approach is correct as this is for a large project that hopefully will convert 10 years of spaghetti code into an organized system.

The code below has been separated into three layers and it works great so far. The API (works together with some HTML & CSS and AJAX as the presentation layer), Business Logic Layer, and a Data Access Layer. I'm using Slim as you can see for the API.

A few questions I have are:

  1. In general, is this a proper way to get the layers working together?
  2. Should the SQL query itself "SELECT x, y, z FROM ..." be contained in the business layer as below, or in the DataLayer, or are there times you may require SQL in both BLL and DAL? I've seen both, but restricted to BLL seems like a more logical separation.
  3. In the example below you can see I'm getting users by company_id. What if I wanted by company_id and isadmin? Would best practice be to associate another route and method for that, such as /users/company/:id/admins with another method such as getAdminUsers()? Doesn't seem right as I could pass parameters to getUsers($id, $isadmin), but not sure what is best practice here.

API

<?php

    require $_SERVER["DOCUMENT_ROOT"] . '/BLL/BLL.php';
    require 'Slim/Slim.php';

    $app = new Slim();

    $app->get('/users/company/:id', 'getUsers');
    $app->get('/users/:id', 'getUser');
    $app->post('/users', 'addUser');
    $app->put('/users/:id', 'updateUser');
    $app->delete('/users/:id',  'deleteUser');

    $app->run();

    function getUsers($id) {
        $bll = new BusinessLayer();
        $result = json_encode($bll->getAllUsersBLL($id));
        echo '{"user": ' . $result  . '}';
    }
?>

Business Logic Layer

<?php

    require_once $_SERVER["DOCUMENT_ROOT"] . "/DAL/DAL.php";

    class BusinessLayer 
    {
        var $dal;

        function __construct() {
            $this->dal = new DataLayer();
        }

        public function getAllUsersBLL($id) {
            $sql = "SELECT * FROM users WHERE company_id = :id ORDER BY id";
            $ret = $this->dal->query($sql, $id);

            return $ret;
        }
     }
  }
?>

Data Access Layer

<?php

    class DataLayer 
    {
        public function connect() {
            $dbhost = "localhost";
            $dbuser = "root";
            $dbpass = "";
            $dbname = "testdatabase";
            $db = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);  
            $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

            return $db;
        }

        public function query($sql, $id) {
            try {
                $db = $this->connect();
                $stmt = $db->prepare($sql);  
                $stmt->bindParam("id", $id);
                $stmt->execute();
                $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
                $db = null;
                return $result;
            } catch(PDOException $e) {
                echo '{"error":{"text":'. $e->getMessage() .'}}'; 
            }
        }
     }
 ?>

Any other feedback is more than welcome!

Michael Hommé
  • 1,696
  • 1
  • 14
  • 18
  • Rather than have `connect()` create and return a new `PDO` object every time, you ought to store it into `$this->connection` and return that object if not null. If it is still null, then create the connection and return it. Otherwiser, every time you call `query()` you will be opening a new database connection, potentially using up all your server's available connections. – Michael Berkowski May 27 '15 at 00:04
  • @MichaelBerkowski - Thanks for the reply, will certainly make that change. – Michael Hommé May 27 '15 at 19:12

0 Answers0