Organizing directory structure of an API centric w

2019-07-28 02:11发布

问题:

Below is a directory structure for a PHP application I have pieced together from examples that provides accessibility via a central (api.php) entry point, no namespaces yet, and class names are identical to file names.


I have separated directories into

  • authentication (has login scripts to process log in, logout, create user
  • config (site wide settings, database settings)


  • controllers (holds class files, with member functions that call specific data method)
  • models (makes simple CRUD operation calls)
  • data (composite operation methods, which call multiple simple method calls)


  • utilities (or 'libraries', that are external to application)

  • vendor (I don't know what to call this, but it autoloads a class)


Like so

├── api.class.php                  <------------- Routes all requests to  controller method using HTTP method name (GET, PUT, POST, DELETE)            
├── api.php                        <------------- Calls processRequest from api.class.php
├── authentication                  
│   └── authenticate.php           <------------- Specifies log in, logout, register logic          
├── config                          
│   └── database.php                
├── controllers
│   ├── <nameof>Controller.php     <------------- Calls a data method from data class (actionitems.php for example)
│   ├── LoginController.php        <------------- Call specific authenticate.php methods
├── data
│   ├── actionitems.php            <------------- Calls several model operations
│   └── users.php
├── models
│   └── actionitem.php             <------------- Contains matching attributes with table in database, and simple CRUD methods
├── utilities                            
│   └── <nameoflibrary>.php                                      
└── vendor                            
    └── autoloader.php             <------------- Loads the class needed without namespace

A few clarifying questions arise...


1) Should I keep the models separate from data to separate simple, composite operations?

2) Is it acceptable to remove the Controller suffix on each file in the Controllers directory?

3) What exactly is the model responsible if not all database CRUD operations?

4) Finally, where should login go if a separate API endpoint?

I've seen this many places where we append "Controller" to the file/class.

The autoloader class below does not recognize the suffix, and the url route doesn't use the entire controller name, in fact, it has the data class name (pluralized model file name).


api.php (main entry point)

<?php
    require_once 'vendor/autoloader.php';
    require_once 'api.class.php';

    class MyAPI extends api
    { 
        public function  __construct($request){
            parent::__construct($request);
        }
    }

    $api = new MyAPI($_REQUEST);
    echo $api->processRequest();

api.class.php

<?php
    abstract class api
    {
        protected $endpoint = array();
        protected $verb = '';
        protected $args = array();
        protected $file = null;
        protected $id = null;

        public function __construct(){
           //gets the specific HTTP method type and assigns the url pieces to properties of api class
        }

        public function processRequest() {
           if(count($this->endpoint) > 0){
               $class = $this->endpoint[0];
               if (class_exists($this->endpoint[0], true)) {
                   $method = strtolower($this->method);
                   if (method_exists($class, $method))
                       return $this->_response((new $class())->{$method}($this->id));
                   }
                   return $this->_response("No Endpoint: {$this->endpoint[0]}", 404);
               }
           }
       }
   }

autoloader.php

<?php
    class autoloader
    {
        private $directoryName;
        public function __construct($directoryName)  
        {
            $this->directoryName = $directoryName;
        }  
        public function autoload($className)
        {
            $fileName = strtolower($className).'.php';
            $file = $this->directoryName.'/'.$fileName;
            if (file_exists($file) == false)
            {
                return false;
            }
            include ($file);
        }    
    }
    # nullify any existing autoloads
    spl_autoload_register(null, false);
    # instantiate the autoloader object
    $classes = [
                    new autoloader('config'),
                    new autoloader('data'), 
                    new autoloader('models'), 
                    new autoloader('controllers')
    ];
    # register the loader functions
    foreach ($classes as $class)
        spl_autoload_register(array($class, 'autoload'));

EDIT:

After some more research on the topic of Enterprise Patterns I have settled on breaking my database directories down into separate layers. I will need to decide on how to organize directories in my application possible move them to a parent directory under api called data, database or something similar.

Data Models - Represents individual entities, containing properties unique to model, in the application database

Domain Logic Models - Represents the logical steps and decisions that pertain to app, including data validation and complex business rules

Mappers - provides access to a data source like a database,

Services - responsible for providing the Data Model or collection to the consumer, acting as public interface to the external framework or end customer

Sample structure for data portion of app

Sample screenshot was from this presentation by Aaron Saray.

https://www.slideshare.net/aaronsaray/midwest-php-2013

This question also covers the topic

Organizing the directory structure of my DDD-based web application?