PHP Application layers

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
5
down vote

favorite












I'm dealing with design layers of an application. Basically what I've so far are:



  • Business

  • Architecture: Client-Server

  • Techonologies: PHP+MySQL, HTML5, JS, 3rd parties APIs

My app



  • Data Sources: MySql databases, 3rd party APIs

  • Data Layer: Interface with CRUD operations, PDO for accessing DBs, Classes implementing CRUD interface, Classes for communication with APIs

  • Repository: Classes & Interfaces with bussiness methods for accessing datasource.

  • Business object: value objects and business rules

  • Application layer: controls flow between Data Layer and Presentation.

  • Presentation layer: html design with javascript & ajax & php code. Interacts with application layer for data retrieval

Implementation



Data Source



1x MySQL Database



1x 3rd party api



Data Layer



interface DSOps

/*
* @return array
*/
function read($sql);

/*
* @return array
*/
function readAll($sql);

/*
* @return boolean
*/
function save($sql);

/*
* @return boolean
*/
function delete($sql);




use PDO;

class DSSql implements DSOps

private $bd;

public function __construct( PDO $bd)

$this->bd = $bd;


public function read($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetch(PDO::FETCH_ASSOC);
return $response;


public function readAll($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $response;


public function save($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);



public function borrar($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);





Repositories:



interface QueryClients

/*
* @return Client
*/
public function searchById($id);

/*
* @return array()
*/
public function searchAll();

/*
* @return int
*/
public function count();





class RepoClients implements QueryClients

private $ds;

public function __construct(DSOps $_ds)

$this->ds = $_ds;


/*
* @return array
*/
public function searchById($id)

$sql = " SELECT * FROM clients WHERE id=$id;";
$response=$this->ds->read($sql);
return $response;


/*
* @return array()
*/
public function searchAll()

$sql = " SELECT * FROM clients; ";
$response=$this->searchAll($sql);
return $response;


....



I've multiple modules that implements the same design. When implementing these design I have the following doubts:



  1. Is correct to form queries at repository classes?

  2. Where should I handle SQL errors? Having an SQLError

  3. How should I handle access to APIs?

  4. As my app has role based access for users, how does this impacts my
    design/implementation? Based on logged user role I've create
    different classes using same interface but implementing different
    queries to database.






share|improve this question



















  • Is this part of a larger framework like laravel ?
    – Dan
    Jun 23 at 8:07
















up vote
5
down vote

favorite












I'm dealing with design layers of an application. Basically what I've so far are:



  • Business

  • Architecture: Client-Server

  • Techonologies: PHP+MySQL, HTML5, JS, 3rd parties APIs

My app



  • Data Sources: MySql databases, 3rd party APIs

  • Data Layer: Interface with CRUD operations, PDO for accessing DBs, Classes implementing CRUD interface, Classes for communication with APIs

  • Repository: Classes & Interfaces with bussiness methods for accessing datasource.

  • Business object: value objects and business rules

  • Application layer: controls flow between Data Layer and Presentation.

  • Presentation layer: html design with javascript & ajax & php code. Interacts with application layer for data retrieval

Implementation



Data Source



1x MySQL Database



1x 3rd party api



Data Layer



interface DSOps

/*
* @return array
*/
function read($sql);

/*
* @return array
*/
function readAll($sql);

/*
* @return boolean
*/
function save($sql);

/*
* @return boolean
*/
function delete($sql);




use PDO;

class DSSql implements DSOps

private $bd;

public function __construct( PDO $bd)

$this->bd = $bd;


public function read($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetch(PDO::FETCH_ASSOC);
return $response;


public function readAll($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $response;


public function save($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);



public function borrar($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);





Repositories:



interface QueryClients

/*
* @return Client
*/
public function searchById($id);

/*
* @return array()
*/
public function searchAll();

/*
* @return int
*/
public function count();





class RepoClients implements QueryClients

private $ds;

public function __construct(DSOps $_ds)

$this->ds = $_ds;


/*
* @return array
*/
public function searchById($id)

$sql = " SELECT * FROM clients WHERE id=$id;";
$response=$this->ds->read($sql);
return $response;


/*
* @return array()
*/
public function searchAll()

$sql = " SELECT * FROM clients; ";
$response=$this->searchAll($sql);
return $response;


....



I've multiple modules that implements the same design. When implementing these design I have the following doubts:



  1. Is correct to form queries at repository classes?

  2. Where should I handle SQL errors? Having an SQLError

  3. How should I handle access to APIs?

  4. As my app has role based access for users, how does this impacts my
    design/implementation? Based on logged user role I've create
    different classes using same interface but implementing different
    queries to database.






share|improve this question



















  • Is this part of a larger framework like laravel ?
    – Dan
    Jun 23 at 8:07












up vote
5
down vote

favorite









up vote
5
down vote

favorite











I'm dealing with design layers of an application. Basically what I've so far are:



  • Business

  • Architecture: Client-Server

  • Techonologies: PHP+MySQL, HTML5, JS, 3rd parties APIs

My app



  • Data Sources: MySql databases, 3rd party APIs

  • Data Layer: Interface with CRUD operations, PDO for accessing DBs, Classes implementing CRUD interface, Classes for communication with APIs

  • Repository: Classes & Interfaces with bussiness methods for accessing datasource.

  • Business object: value objects and business rules

  • Application layer: controls flow between Data Layer and Presentation.

  • Presentation layer: html design with javascript & ajax & php code. Interacts with application layer for data retrieval

Implementation



Data Source



1x MySQL Database



1x 3rd party api



Data Layer



interface DSOps

/*
* @return array
*/
function read($sql);

/*
* @return array
*/
function readAll($sql);

/*
* @return boolean
*/
function save($sql);

/*
* @return boolean
*/
function delete($sql);




use PDO;

class DSSql implements DSOps

private $bd;

public function __construct( PDO $bd)

$this->bd = $bd;


public function read($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetch(PDO::FETCH_ASSOC);
return $response;


public function readAll($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $response;


public function save($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);



public function borrar($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);





Repositories:



interface QueryClients

/*
* @return Client
*/
public function searchById($id);

/*
* @return array()
*/
public function searchAll();

/*
* @return int
*/
public function count();





class RepoClients implements QueryClients

private $ds;

public function __construct(DSOps $_ds)

$this->ds = $_ds;


/*
* @return array
*/
public function searchById($id)

$sql = " SELECT * FROM clients WHERE id=$id;";
$response=$this->ds->read($sql);
return $response;


/*
* @return array()
*/
public function searchAll()

$sql = " SELECT * FROM clients; ";
$response=$this->searchAll($sql);
return $response;


....



I've multiple modules that implements the same design. When implementing these design I have the following doubts:



  1. Is correct to form queries at repository classes?

  2. Where should I handle SQL errors? Having an SQLError

  3. How should I handle access to APIs?

  4. As my app has role based access for users, how does this impacts my
    design/implementation? Based on logged user role I've create
    different classes using same interface but implementing different
    queries to database.






share|improve this question











I'm dealing with design layers of an application. Basically what I've so far are:



  • Business

  • Architecture: Client-Server

  • Techonologies: PHP+MySQL, HTML5, JS, 3rd parties APIs

My app



  • Data Sources: MySql databases, 3rd party APIs

  • Data Layer: Interface with CRUD operations, PDO for accessing DBs, Classes implementing CRUD interface, Classes for communication with APIs

  • Repository: Classes & Interfaces with bussiness methods for accessing datasource.

  • Business object: value objects and business rules

  • Application layer: controls flow between Data Layer and Presentation.

  • Presentation layer: html design with javascript & ajax & php code. Interacts with application layer for data retrieval

Implementation



Data Source



1x MySQL Database



1x 3rd party api



Data Layer



interface DSOps

/*
* @return array
*/
function read($sql);

/*
* @return array
*/
function readAll($sql);

/*
* @return boolean
*/
function save($sql);

/*
* @return boolean
*/
function delete($sql);




use PDO;

class DSSql implements DSOps

private $bd;

public function __construct( PDO $bd)

$this->bd = $bd;


public function read($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetch(PDO::FETCH_ASSOC);
return $response;


public function readAll($sql)

$stmt=$this->bd->prepare($sql);
$stmt->execute();
$response = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $response;


public function save($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);



public function borrar($sql, $params)

$stmt=$this->bd->prepare($sql);
return $stmt->execute($params);





Repositories:



interface QueryClients

/*
* @return Client
*/
public function searchById($id);

/*
* @return array()
*/
public function searchAll();

/*
* @return int
*/
public function count();





class RepoClients implements QueryClients

private $ds;

public function __construct(DSOps $_ds)

$this->ds = $_ds;


/*
* @return array
*/
public function searchById($id)

$sql = " SELECT * FROM clients WHERE id=$id;";
$response=$this->ds->read($sql);
return $response;


/*
* @return array()
*/
public function searchAll()

$sql = " SELECT * FROM clients; ";
$response=$this->searchAll($sql);
return $response;


....



I've multiple modules that implements the same design. When implementing these design I have the following doubts:



  1. Is correct to form queries at repository classes?

  2. Where should I handle SQL errors? Having an SQLError

  3. How should I handle access to APIs?

  4. As my app has role based access for users, how does this impacts my
    design/implementation? Based on logged user role I've create
    different classes using same interface but implementing different
    queries to database.








share|improve this question










share|improve this question




share|improve this question









asked Jun 23 at 2:43









jcruz

261




261











  • Is this part of a larger framework like laravel ?
    – Dan
    Jun 23 at 8:07
















  • Is this part of a larger framework like laravel ?
    – Dan
    Jun 23 at 8:07















Is this part of a larger framework like laravel ?
– Dan
Jun 23 at 8:07




Is this part of a larger framework like laravel ?
– Dan
Jun 23 at 8:07










1 Answer
1






active

oldest

votes

















up vote
4
down vote













SQL injection



First of all, your PDO code is a straw plane that never flies. Using prepare() like that makes very little sense, leaving all your queries widely exposed to SQL injection attacks.



prepare() doesn't protect your queries by itself, making them immune by means of some magic. It helps only if you take out every single variable from your query and substitute it with a placeholder, then prepare your query and then finally execute, adding variables separately.



Therefore, all methods in DSSql should be changed in order to accept two variables - a query and an array with data:



public function read($sql, $params = )

$stmt=$this->bd->prepare($sql);
$stmt->execute($params);
$response = $stmt->fetch(PDO::FETCH_ASSOC);
return $response;



Code duplication



As you may notice, the code in DSSql class' methods is heavily duplicated. Why not to create a basic method to run an arbitrary query, an then call this method with only different return formats?



public function query($sql, $params = )

$stmt=$this->bd->prepare($sql);
$stmt->execute($params);
return $stmt;


public function read($sql, $params = )

return $this->query($sql, $params)->fetch(PDO::FETCH_ASSOC);


public function readAll($sql)

return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);


public function save($sql, $params)

return $this->query($sql, $params);



Existing PHP classes' code reuse



As you may notice, your methods now bear very little difference. Why not to take them out at all and make use of the powerful PDOSTatement class already exists in PHP?



public function searchById($id)

$sql = "SELECT * FROM clients WHERE id=?";
return $this->ds->query($sql, [$id])->fetch();


public function searchAll()

$sql = "SELECT * FROM clients";
return $this->query($sql)->fetchAll();



ORM



The code in the save() method is not really does the save but rater runs an arbitrary query, which could be quite confusing. If you want a real save, read and such methods, consider using an ORM, a class that constructs SQL queries for you, and in such a case it will be indeed save() or find() with no other meaning



Questions




Is correct to form queries at repository classes?




yes, it's the place where SQL belongs




Where should I handle SQL errors? Having an SQLError




Wherever you are handling all other errors. There is nothing special in SQL errors, handle them the same way as others.




How should I handle access to APIs?




That is somewhat too wide question for a comment, especially without any context given. May be you should ask on Stack Overflow.




As my app has role based access for users, how does this impacts my design/implementation? Based on logged user role I've create different classes using same interface but implementing different queries to database.




Well, this is somewhat a key question. Consider using an existing framework instead of rolling up a your own. Established frameworks already have all you need out of the box, including ORM, a template engine and of course a user management module with role based authorization. I would suggest Symfony as being the most popular PHP framework that encourages best coding practices.






share|improve this answer























    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197095%2fphp-application-layers%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    4
    down vote













    SQL injection



    First of all, your PDO code is a straw plane that never flies. Using prepare() like that makes very little sense, leaving all your queries widely exposed to SQL injection attacks.



    prepare() doesn't protect your queries by itself, making them immune by means of some magic. It helps only if you take out every single variable from your query and substitute it with a placeholder, then prepare your query and then finally execute, adding variables separately.



    Therefore, all methods in DSSql should be changed in order to accept two variables - a query and an array with data:



    public function read($sql, $params = )

    $stmt=$this->bd->prepare($sql);
    $stmt->execute($params);
    $response = $stmt->fetch(PDO::FETCH_ASSOC);
    return $response;



    Code duplication



    As you may notice, the code in DSSql class' methods is heavily duplicated. Why not to create a basic method to run an arbitrary query, an then call this method with only different return formats?



    public function query($sql, $params = )

    $stmt=$this->bd->prepare($sql);
    $stmt->execute($params);
    return $stmt;


    public function read($sql, $params = )

    return $this->query($sql, $params)->fetch(PDO::FETCH_ASSOC);


    public function readAll($sql)

    return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);


    public function save($sql, $params)

    return $this->query($sql, $params);



    Existing PHP classes' code reuse



    As you may notice, your methods now bear very little difference. Why not to take them out at all and make use of the powerful PDOSTatement class already exists in PHP?



    public function searchById($id)

    $sql = "SELECT * FROM clients WHERE id=?";
    return $this->ds->query($sql, [$id])->fetch();


    public function searchAll()

    $sql = "SELECT * FROM clients";
    return $this->query($sql)->fetchAll();



    ORM



    The code in the save() method is not really does the save but rater runs an arbitrary query, which could be quite confusing. If you want a real save, read and such methods, consider using an ORM, a class that constructs SQL queries for you, and in such a case it will be indeed save() or find() with no other meaning



    Questions




    Is correct to form queries at repository classes?




    yes, it's the place where SQL belongs




    Where should I handle SQL errors? Having an SQLError




    Wherever you are handling all other errors. There is nothing special in SQL errors, handle them the same way as others.




    How should I handle access to APIs?




    That is somewhat too wide question for a comment, especially without any context given. May be you should ask on Stack Overflow.




    As my app has role based access for users, how does this impacts my design/implementation? Based on logged user role I've create different classes using same interface but implementing different queries to database.




    Well, this is somewhat a key question. Consider using an existing framework instead of rolling up a your own. Established frameworks already have all you need out of the box, including ORM, a template engine and of course a user management module with role based authorization. I would suggest Symfony as being the most popular PHP framework that encourages best coding practices.






    share|improve this answer



























      up vote
      4
      down vote













      SQL injection



      First of all, your PDO code is a straw plane that never flies. Using prepare() like that makes very little sense, leaving all your queries widely exposed to SQL injection attacks.



      prepare() doesn't protect your queries by itself, making them immune by means of some magic. It helps only if you take out every single variable from your query and substitute it with a placeholder, then prepare your query and then finally execute, adding variables separately.



      Therefore, all methods in DSSql should be changed in order to accept two variables - a query and an array with data:



      public function read($sql, $params = )

      $stmt=$this->bd->prepare($sql);
      $stmt->execute($params);
      $response = $stmt->fetch(PDO::FETCH_ASSOC);
      return $response;



      Code duplication



      As you may notice, the code in DSSql class' methods is heavily duplicated. Why not to create a basic method to run an arbitrary query, an then call this method with only different return formats?



      public function query($sql, $params = )

      $stmt=$this->bd->prepare($sql);
      $stmt->execute($params);
      return $stmt;


      public function read($sql, $params = )

      return $this->query($sql, $params)->fetch(PDO::FETCH_ASSOC);


      public function readAll($sql)

      return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);


      public function save($sql, $params)

      return $this->query($sql, $params);



      Existing PHP classes' code reuse



      As you may notice, your methods now bear very little difference. Why not to take them out at all and make use of the powerful PDOSTatement class already exists in PHP?



      public function searchById($id)

      $sql = "SELECT * FROM clients WHERE id=?";
      return $this->ds->query($sql, [$id])->fetch();


      public function searchAll()

      $sql = "SELECT * FROM clients";
      return $this->query($sql)->fetchAll();



      ORM



      The code in the save() method is not really does the save but rater runs an arbitrary query, which could be quite confusing. If you want a real save, read and such methods, consider using an ORM, a class that constructs SQL queries for you, and in such a case it will be indeed save() or find() with no other meaning



      Questions




      Is correct to form queries at repository classes?




      yes, it's the place where SQL belongs




      Where should I handle SQL errors? Having an SQLError




      Wherever you are handling all other errors. There is nothing special in SQL errors, handle them the same way as others.




      How should I handle access to APIs?




      That is somewhat too wide question for a comment, especially without any context given. May be you should ask on Stack Overflow.




      As my app has role based access for users, how does this impacts my design/implementation? Based on logged user role I've create different classes using same interface but implementing different queries to database.




      Well, this is somewhat a key question. Consider using an existing framework instead of rolling up a your own. Established frameworks already have all you need out of the box, including ORM, a template engine and of course a user management module with role based authorization. I would suggest Symfony as being the most popular PHP framework that encourages best coding practices.






      share|improve this answer

























        up vote
        4
        down vote










        up vote
        4
        down vote









        SQL injection



        First of all, your PDO code is a straw plane that never flies. Using prepare() like that makes very little sense, leaving all your queries widely exposed to SQL injection attacks.



        prepare() doesn't protect your queries by itself, making them immune by means of some magic. It helps only if you take out every single variable from your query and substitute it with a placeholder, then prepare your query and then finally execute, adding variables separately.



        Therefore, all methods in DSSql should be changed in order to accept two variables - a query and an array with data:



        public function read($sql, $params = )

        $stmt=$this->bd->prepare($sql);
        $stmt->execute($params);
        $response = $stmt->fetch(PDO::FETCH_ASSOC);
        return $response;



        Code duplication



        As you may notice, the code in DSSql class' methods is heavily duplicated. Why not to create a basic method to run an arbitrary query, an then call this method with only different return formats?



        public function query($sql, $params = )

        $stmt=$this->bd->prepare($sql);
        $stmt->execute($params);
        return $stmt;


        public function read($sql, $params = )

        return $this->query($sql, $params)->fetch(PDO::FETCH_ASSOC);


        public function readAll($sql)

        return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);


        public function save($sql, $params)

        return $this->query($sql, $params);



        Existing PHP classes' code reuse



        As you may notice, your methods now bear very little difference. Why not to take them out at all and make use of the powerful PDOSTatement class already exists in PHP?



        public function searchById($id)

        $sql = "SELECT * FROM clients WHERE id=?";
        return $this->ds->query($sql, [$id])->fetch();


        public function searchAll()

        $sql = "SELECT * FROM clients";
        return $this->query($sql)->fetchAll();



        ORM



        The code in the save() method is not really does the save but rater runs an arbitrary query, which could be quite confusing. If you want a real save, read and such methods, consider using an ORM, a class that constructs SQL queries for you, and in such a case it will be indeed save() or find() with no other meaning



        Questions




        Is correct to form queries at repository classes?




        yes, it's the place where SQL belongs




        Where should I handle SQL errors? Having an SQLError




        Wherever you are handling all other errors. There is nothing special in SQL errors, handle them the same way as others.




        How should I handle access to APIs?




        That is somewhat too wide question for a comment, especially without any context given. May be you should ask on Stack Overflow.




        As my app has role based access for users, how does this impacts my design/implementation? Based on logged user role I've create different classes using same interface but implementing different queries to database.




        Well, this is somewhat a key question. Consider using an existing framework instead of rolling up a your own. Established frameworks already have all you need out of the box, including ORM, a template engine and of course a user management module with role based authorization. I would suggest Symfony as being the most popular PHP framework that encourages best coding practices.






        share|improve this answer















        SQL injection



        First of all, your PDO code is a straw plane that never flies. Using prepare() like that makes very little sense, leaving all your queries widely exposed to SQL injection attacks.



        prepare() doesn't protect your queries by itself, making them immune by means of some magic. It helps only if you take out every single variable from your query and substitute it with a placeholder, then prepare your query and then finally execute, adding variables separately.



        Therefore, all methods in DSSql should be changed in order to accept two variables - a query and an array with data:



        public function read($sql, $params = )

        $stmt=$this->bd->prepare($sql);
        $stmt->execute($params);
        $response = $stmt->fetch(PDO::FETCH_ASSOC);
        return $response;



        Code duplication



        As you may notice, the code in DSSql class' methods is heavily duplicated. Why not to create a basic method to run an arbitrary query, an then call this method with only different return formats?



        public function query($sql, $params = )

        $stmt=$this->bd->prepare($sql);
        $stmt->execute($params);
        return $stmt;


        public function read($sql, $params = )

        return $this->query($sql, $params)->fetch(PDO::FETCH_ASSOC);


        public function readAll($sql)

        return $this->query($sql)->fetchAll(PDO::FETCH_ASSOC);


        public function save($sql, $params)

        return $this->query($sql, $params);



        Existing PHP classes' code reuse



        As you may notice, your methods now bear very little difference. Why not to take them out at all and make use of the powerful PDOSTatement class already exists in PHP?



        public function searchById($id)

        $sql = "SELECT * FROM clients WHERE id=?";
        return $this->ds->query($sql, [$id])->fetch();


        public function searchAll()

        $sql = "SELECT * FROM clients";
        return $this->query($sql)->fetchAll();



        ORM



        The code in the save() method is not really does the save but rater runs an arbitrary query, which could be quite confusing. If you want a real save, read and such methods, consider using an ORM, a class that constructs SQL queries for you, and in such a case it will be indeed save() or find() with no other meaning



        Questions




        Is correct to form queries at repository classes?




        yes, it's the place where SQL belongs




        Where should I handle SQL errors? Having an SQLError




        Wherever you are handling all other errors. There is nothing special in SQL errors, handle them the same way as others.




        How should I handle access to APIs?




        That is somewhat too wide question for a comment, especially without any context given. May be you should ask on Stack Overflow.




        As my app has role based access for users, how does this impacts my design/implementation? Based on logged user role I've create different classes using same interface but implementing different queries to database.




        Well, this is somewhat a key question. Consider using an existing framework instead of rolling up a your own. Established frameworks already have all you need out of the box, including ORM, a template engine and of course a user management module with role based authorization. I would suggest Symfony as being the most popular PHP framework that encourages best coding practices.







        share|improve this answer















        share|improve this answer



        share|improve this answer








        edited Jun 23 at 9:37


























        answered Jun 23 at 9:04









        Your Common Sense

        2,405523




        2,405523






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f197095%2fphp-application-layers%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Greedy Best First Search implementation in Rust

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            C++11 CLH Lock Implementation