-
Mar 8th, 2021, 08:14 PM
#1
[PHP] Project Architecture
Hi every, thank you for taking the time to visit this thread. Here is the background, I am wanting to eventually start my own software development company and right now I have secured a contract job to build out a ticket maintenance system for an offshore company. What I'm wanting to do is develop a base stack so that I can use it going forward on future projects.
I have written a simple console application that takes the following arguments so that it automatically generates the code that I'm displaying below:
- Table name
- Column names
- File type (model, database, service, api)
In my next several posts, I will provide the code that I am currently using to represent my Menu table in my database.
For visibility, this is what the file structure looks like:
Code:
root
├── pages
├── server
│ ├── api
│ ├── database
│ ├── model
│ ├── service
│ └── utilities
└── vendor
What I am hoping to achieve is direction on:
- Does this code structure make sense to other developers. I.e. if you were to inherit this project with no knowledge of who I am or how the project was developed, would it take too much effor to maintain
- Can the code be simplified?
- What suggestions do y'all have?
Last edited by dday9; Mar 8th, 2021 at 08:23 PM.
-
Mar 8th, 2021, 08:14 PM
#2
Re: [PHP] Project Architecture
The first piece of code represents a POCO representation of the database table, stored in root/server/model, named [table-name].php:
Code:
<?php
class MenuModel {
public static $TableName ='Menu';
public static $ColumnNames = [
'MenuId',
'MenuName',
'MenuSlug',
'CreatedBy',
'CreatedOn',
'ModifiedBy',
'ModifiedOn',
'DeletedOn'
];
public static $RequiredColumnNames = [
'MenuId',
'MenuName',
'MenuSlug'
];
/**
* property definition for MenuId
*/
public $MenuId;
/**
* getter for MenuId
*/
private function getMenuId() {
return $this->MenuId;
}
/**
* setter for MenuId
*/
private function setMenuId($menuId) {
$this->MenuId = $menuId;
}
/**
* property definition for MenuName
*/
public $MenuName;
/**
* getter for MenuName
*/
private function getMenuName() {
return $this->MenuName;
}
/**
* setter for MenuName
*/
private function setMenuName($menuName) {
$this->MenuName = $menuName;
}
/**
* property definition for MenuSlug
*/
public $MenuSlug;
/**
* getter for MenuSlug
*/
private function getMenuSlug() {
return $this->MenuSlug;
}
/**
* setter for MenuSlug
*/
private function setMenuSlug($menuSlug) {
$this->MenuSlug = $menuSlug;
}
/**
* property definition for CreatedBy
*/
public $CreatedBy;
/**
* getter for CreatedBy
*/
private function getCreatedBy() {
return $this->CreatedBy;
}
/**
* setter for CreatedBy
*/
private function setCreatedBy($createdBy) {
$this->CreatedBy = $createdBy;
}
/**
* property definition for CreatedOn
*/
public $CreatedOn;
/**
* getter for CreatedOn
*/
private function getCreatedOn() {
return $this->CreatedOn;
}
/**
* setter for CreatedOn
*/
private function setCreatedOn($createdOn) {
$this->CreatedOn = $createdOn;
}
/**
* property definition for ModifiedBy
*/
public $ModifiedBy;
/**
* getter for ModifiedBy
*/
private function getModifiedBy() {
return $this->ModifiedBy;
}
/**
* setter for ModifiedBy
*/
private function setModifiedBy($modifiedBy) {
$this->ModifiedBy = $modifiedBy;
}
/**
* property definition for ModifiedOn
*/
public $ModifiedOn;
/**
* getter for ModifiedOn
*/
private function getModifiedOn() {
return $this->ModifiedOn;
}
/**
* setter for ModifiedOn
*/
private function setModifiedOn($modifiedOn) {
$this->ModifiedOn = $modifiedOn;
}
/**
* property definition for DeletedOn
*/
public $DeletedOn;
/**
* getter for DeletedOn
*/
private function getDeletedOn() {
return $this->DeletedOn;
}
/**
* setter for DeletedOn
*/
private function setDeletedOn($deletedOn) {
$this->DeletedOn = $deletedOn;
}
/**
* property definition for CreatedByUsername
*/
public $CreatedByUsername;
/**
* getter for CreatedByUsername
*/
private function getCreatedByUsername() {
return $this->CreatedByUsername;
}
/**
* setter for CreatedByUsername
*/
private function setCreatedByUsername($createdByUsername) {
$this->CreatedByUsername = $createdByUsername;
}
/**
* property definition for ModifiedByUsername
*/
public $ModifiedByUsername;
/**
* getter for ModifiedByUsername
*/
private function getModifiedByUsername() {
return $this->ModifiedByUsername;
}
/**
* setter for ModifiedByUsername
*/
private function setModifiedByUsername($modifiedByUsername) {
$this->ModifiedByUsername = $modifiedByUsername;
}
/**
* magic getter
*/
public function __set($name, $value) {
switch($name) {
case 'MenuId':
return $this->setMenuId($value);
case 'MenuName':
return $this->setMenuName($value);
case 'MenuSlug':
return $this->setMenuSlug($value);
case 'CreatedBy':
return $this->setCreatedBy($value);
case 'CreatedOn':
return $this->setCreatedOn($value);
case 'ModifiedBy':
return $this->setModifiedBy($value);
case 'ModifiedOn':
return $this->setModifiedOn($value);
case 'DeletedOn':
return $this->setDeletedOn($value);
case 'CreatedByUsername':
return $this->setCreatedByUsername($value);
case 'ModifiedByUsername':
return $this->setModifiedByUsername($value);
}
}
/**
* magic setter
*/
public function __get($name) {
switch($name) {
case 'MenuId':
return $this->getMenuId();
case 'MenuName':
return $this->getMenuName();
case 'MenuSlug':
return $this->getMenuSlug();
case 'CreatedBy':
return $this->getCreatedBy();
case 'CreatedOn':
return $this->getCreatedOn();
case 'ModifiedBy':
return $this->getModifiedBy();
case 'ModifiedOn':
return $this->getModifiedOn();
case 'DeletedOn':
return $this->getDeletedOn();
case 'CreatedByUsername':
return $this->getCreatedByUsername();
case 'ModifiedByUsername':
return $this->getModifiedByUsername();
}
}
}
?>
This next piece of code represents the methods to perform the CRUD operations against the database, stored in root/server/database, named [table-name].php:
Code:
<?php
require_once(__DIR__ . '/../model/menu.php');
require_once(__DIR__ . '/../utilities/database.php');
class MenuDatabase extends DatabaseRoot {
public static function create($menu, $createdBy = null) {
if (!($menu instanceof MenuModel)) {
throw new Exception('menu argument is not a MenuModel');
}
$sql = '
INSERT INTO Menu (
MenuName,
MenuSlug,
CreatedBy,
CreatedOn
) VALUES (
:menuName,
:menuSlug,
:createdBy,
CURRENT_TIMESTAMP()
);
';
$database = new DatabaseUtility();
$connection = $database->getConnection();
$statement = $connection->prepare($sql);
$statement->bindParam(':menuName', $menu->MenuName);
$statement->bindParam(':menuSlug', $menu->MenuSlug);
if (is_null($createdBy)) {
$statement->bindValue(':createdBy', null, PDO::PARAM_NULL);
} else {
$statement->bindParam(':createdBy', $createdBy);
}
$statement->execute();
$recordId = $connection->lastInsertId();
$filter = array();
$filter['MenuId'] = $recordId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('Something went wrong creating the record.');
}
return $records['records'][0];
}
public static function delete($menuId, $modifiedBy = null) {
if (!(is_numeric($menuId) && ctype_digit(strval($menuId)))) {
throw new Exception('$menuId argument is not a valid id.');
}
$filter = array();
$filter['MenuId'] = $menuId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('The record does not exist with Id: ' . $menuId);
}
$sql = '
UPDATE
Menu
SET
ModifiedBy = :modifiedBy,
DeletedOn = CURRENT_TIMESTAMP()
WHERE
MenuId = :menuId;
';
$database = new DatabaseUtility();
$connection = $database->getConnection();
$statement = $connection->prepare($sql);
if (is_null($modifiedBy)) {
$statement->bindValue(':modifiedBy', null, PDO::PARAM_NULL);
} else {
$statement->bindParam(':modifiedBy', $modifiedBy);
}
$statement->bindParam(':menuId', $menuId);
$statement->execute();
$filter = array();
$filter['MenuId'] = $menuId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('Something went wrong deleting the record.');
}
return $records['records'][0];
}
public static function query($filters) {
$parameters = array();
$where = array();
$orderBy = ' ORDER BY Menu.MenuName';
$sql = '
SELECT
Menu.*,
UserCreatedBy.Username AS CreatedByUsername,
UserModifiedBy.Username AS CreatedByUsername
FROM
Menu
LEFT OUTER JOIN
`User` AS UserCreatedBy ON Menu.CreatedBy = UserCreatedBy.UserId
LEFT OUTER JOIN
`User` AS UserModifiedBy ON Menu.ModifiedBy = UserModifiedBy.UserId';
if ($filters) {
foreach ($filters as $key => $value) {
$filters[ucfirst($key)] = $value;
unset($filters[lcfirst($key)]);
}
if (array_key_exists('IncludeDeleted', $filters) && $filters['IncludeDeleted'] == 'false') {
unset($filters['IncludeDeleted']);
$filters['DeletedOn_Null'] = true;
}
DatabaseUtility::processFilter($filters, MenuModel::$TableName, MenuModel::$ColumnNames, $parameters, $where);
if ($where) {
$sql .= ' WHERE ' . join(' AND ', $where);
}
}
if ($orderBy) {
$sql .= $orderBy . ';';
}
$database = new DatabaseUtility();
$connection = $database->getConnection();
$statement = $connection->prepare($sql);
$statement->execute($parameters);
$rowCount = 0;
$result = array();
$result['records'] = array();
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
// MySQL will return a blank row if no rows were returned,
// If every property is null, then skip this row
$continue = false;
foreach (MenuModel::$ColumnNames as $value) {
if (!is_null($row[$value])) {
$continue = true;
}
}
if (!$continue) {
continue;
}
$rowCount++;
extract($row);
$record = array(
'MenuId' => $MenuId,
'MenuName' => $MenuName,
'MenuSlug' => $MenuSlug,
'CreatedBy' => $CreatedBy,
'CreatedOn' => $CreatedOn,
'ModifiedBy' => $ModifiedBy,
'ModifiedOn' => $ModifiedOn,
'DeletedOn' => $DeletedOn
);
array_push($result['records'], $record);
}
$result['total'] = $rowCount;
return $result;
}
public static function undelete($menuId, $modifiedBy = null) {
if (!(is_numeric($menuId) && ctype_digit(strval($menuId)))) {
throw new Exception('$menuId argument is not a valid id.');
}
$filter = array();
$filter['MenuId'] = $menuId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('The record does not exist with Id: ' . $menuId);
}
$sql = '
UPDATE
Menu
SET
ModifiedBy = :modifiedBy,
DeletedOn = NULL
WHERE
MenuId = :menuId;
';
$database = new DatabaseUtility();
$connection = $database->getConnection();
$statement = $connection->prepare($sql);
if (is_null($modifiedBy)) {
$statement->bindValue(':modifiedBy', null, PDO::PARAM_NULL);
} else {
$statement->bindParam(':modifiedBy', $modifiedBy);
}
$statement->bindParam(':menuId', $menuId);
$statement->execute();
$filter = array();
$filter['MenuId'] = $menuId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('Something went wrong restoring the record.');
}
return $records['records'][0];
}
public static function update($menuId, $menu, $modifiedBy = null) {
if (!(is_numeric($menuId) && ctype_digit(strval($menuId)))) {
throw new Exception('$menuId argument is not a valid id.');
}
if (!($menu instanceof MenuModel)) {
throw new Exception('menu argument is not a MenuModel');
}
$filter = array();
$filter['MenuId'] = $menuId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('The record does not exist with Id: ' . $menuId);
}
// MenuSlug is not included, slugs are immutable
$sql = '
UPDATE
Menu
SET
MenuName = :menuName,
ModifiedBy = :modifiedBy,
ModifiedOn = CURRENT_TIMESTAMP()
WHERE
MenuId = :menuId;
';
$database = new DatabaseUtility();
$connection = $database->getConnection();
$statement = $connection->prepare($sql);
$statement->bindParam(':menuName', $menu->MenuName);
if (is_null($modifiedBy)) {
$statement->bindValue(':modifiedBy', null, PDO::PARAM_NULL);
} else {
$statement->bindParam(':modifiedBy', $modifiedBy);
}
$statement->bindParam(':menuId', $menuId);
$statement->execute();
$filter = array();
$filter['MenuId'] = $menuId;
$records = MenuDatabase::query($filter);
if ($records['total'] !== 1) {
throw new Exception('Something went wrong updating the record.');
}
return $records['records'][0];
}
}
?>
-
Mar 8th, 2021, 08:16 PM
#3
Re: [PHP] Project Architecture
This next piece of code represents a middle layer between the API request and the database operation, stored in root/server/service, named [table-name].php:
Any business logic specific to the model gets applied here. E.g. look at how the create method is creating a slug for MenuSlug in MenuService::create
Code:
<?php
require_once(__DIR__ . '/../model/menu.php');
require_once(__DIR__ . '/../database/menu.php');
require_once(__DIR__ . '/../utilities/text.php');
class MenuService {
public static function create($menu, $createdBy = null) {
$menu->MenuSlug = TextUtility::slugify($menu->MenuName);
$record = MenuDatabase::create($menu, $createdBy);
return $record;
}
public static function delete($menuId, $modifiedBy = null) {
$record = MenuDatabase::delete($menuId, $modifiedBy);
return $record;
}
public static function get($menuId) {
$filters = array();
$filters['MenuId'] = $menuId;
$records = MenuService::query($filters);
if ($records['total'] === 0) {
throw new Exception('No record with id: ' . $menuId, 404);
}
if ($records['total'] > 1) {
throw new Exception('Multiple records with id: ' . $menuId);
}
return $records['records'][0];
}
public static function query($filters) {
$records = MenuDatabase::query($filters);
return $records;
}
public static function undelete($menuId, $modifiedBy = null) {
$record = MenuDatabase::undelete($menuId, $modifiedBy);
return $record;
}
public static function update($menuId, $menu, $modifiedBy = null) {
$existing = MenuService::Get($menuId);
$updating = new MenuModel();
foreach (MenuModel::$ColumnNames as $value) {
if ($value === 'MenuId') {
continue;
}
$property = $menu->$value;
if (!$property) {
$updating->$value = $existing[$value];
} else {
$updating->$value = $property;
}
}
$record = MenuDatabase::update($menuId, $updating, $modifiedBy);
return $record;
}
}
?>
-
Mar 8th, 2021, 08:16 PM
#4
Re: [PHP] Project Architecture
This next piece of code represents the API request to create a record, stored in root/api/[table-name], named create.php:
Code:
<?php
// imports
require_once(__DIR__ . '/../../model/menu.php');
require_once(__DIR__ . '/../../service/menu.php');
require_once(__DIR__ . '/../../utilities/auth.php');
require_once(__DIR__ . '/../../utilities/controller.php');
// return headers/body
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
$returnedJson = array();
$url = 'server/api/menu/create.php';
$currentUserId = AuthUtility::assertUserIdInHeaders(apache_request_headers());
// check for unauthorized request
if (!ControllerUtility::assertSystemActionPermission($url, $currentUserId)) {
return;
}
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a POST request.';
echo json_encode($returnedJson);
return;
}
if (!$_POST) {
$rest_json = file_get_contents("php://input");
$_POST = json_decode($rest_json, true);
}
// check for bad request
$errors = array();
$menu = new MenuModel();
foreach (MenuModel::$RequiredColumnNames as $property) {
$success = ControllerUtility::isValueInRequest($_POST, $property);
if (!$success) {
array_push($errors, $property);
continue;
}
$menu->$property = $_POST[$property];
}
if (count($errors) > 0) {
http_response_code(400);
$returnedJson['error'] = 'Malformed request syntax. The following properties are missing from the request: ' . join(', ', $errors);
echo json_encode($returnedJson);
return;
}
// create the record
try {
$record = MenuService::create($menu, $currentUserId);
http_response_code(201);
$returnedJson = $record;
}
catch (exception $e) {
$statusCode = (!($e->getCode()) ? 500 : $e->getCode());
http_response_code($statusCode);
$returnedJson['error'] = $e->getMessage();
}
echo json_encode($returnedJson);
?>
This next piece of code represents the API request to delete a record, stored in root/api/[table-name], named delete.php:
Code:
<?php
// imports
require_once(__DIR__ . '/../../model/menu.php');
require_once(__DIR__ . '/../../service/menu.php');
require_once(__DIR__ . '/../../utilities/auth.php');
require_once(__DIR__ . '/../../utilities/controller.php');
// return headers/body
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
$returnedJson = array();
$url = 'server/api/menu/delete.php';
$currentUserId = AuthUtility::assertUserIdInHeaders(apache_request_headers());
// check for unauthorized request
if (!ControllerUtility::assertSystemActionPermission($url, $currentUserId)) {
return;
}
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a GET request.';
echo json_encode($returnedJson);
return;
}
// check for bad request
$errors = array();
$idInRequest = ControllerUtility::isValueInRequest($_GET, 'MenuId');
if (!$idInRequest) {
http_response_code(400);
$returnedJson['error'] = 'Malformed request syntax. The following property is missing from the request: MenuId';
echo json_encode($returnedJson);
return;
}
$id = $_GET['MenuId'];
// delete the record
try {
MenuService::delete($id, $currentUserId);
http_response_code(204);
}
catch (exception $e) {
$statusCode = (!($e->getCode()) ? 500 : $e->getCode());
http_response_code($statusCode);
$returnedJson['error'] = $e->getMessage();
}
echo json_encode($returnedJson);
?>
This next piece of code represents the API request to get a single record, stored in root/api/[table-name], named get.php:
Code:
<?php
// imports
require_once(__DIR__ . '/../../model/menu.php');
require_once(__DIR__ . '/../../service/menu.php');
require_once(__DIR__ . '/../../utilities/auth.php');
require_once(__DIR__ . '/../../utilities/controller.php');
// return headers/body
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
$returnedJson = array();
$url = 'server/api/menu/get.php';
$currentUserId = AuthUtility::assertUserIdInHeaders(apache_request_headers());
// check for unauthorized request
if (!ControllerUtility::assertSystemActionPermission($url, $currentUserId)) {
return;
}
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a GET request.';
echo json_encode($returnedJson);
return;
}
// check for bad request
$errors = array();
$idInRequest = ControllerUtility::isValueInRequest($_GET, 'MenuId');
if (!$idInRequest) {
http_response_code(400);
$returnedJson['error'] = 'Malformed request syntax. The following property is missing from the request: MenuId';
echo json_encode($returnedJson);
return;
}
$id = $_GET['MenuId'];
// get the record
try {
$record = MenuService::get($id);
http_response_code(200);
$returnedJson = $record;
}
catch (exception $e) {
$statusCode = (!($e->getCode()) ? 500 : $e->getCode());
http_response_code($statusCode);
$returnedJson['error'] = $e->getMessage();
}
echo json_encode($returnedJson);
?>
This next piece of code represents the API request to get a zero or more records, stored in root/api/[table-name], named query.php:
Code:
<?php
// imports
require_once(__DIR__ . '/../../model/menu.php');
require_once(__DIR__ . '/../../service/menu.php');
require_once(__DIR__ . '/../../utilities/auth.php');
require_once(__DIR__ . '/../../utilities/controller.php');
// return headers/body
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
$returnedJson = array();
$url = 'server/api/menu/query.php';
$currentUserId = AuthUtility::assertUserIdInHeaders(apache_request_headers());
// check for unauthorized request
if (!ControllerUtility::assertSystemActionPermission($url, $currentUserId)) {
return;
}
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a GET request.';
echo json_encode($returnedJson);
return;
}
// query the database for zero or more records
try {
$records = MenuService::query($_GET);
http_response_code(200);
$returnedJson = $records;
}
catch (exception $e) {
$statusCode = (!($e->getCode()) ? 500 : $e->getCode());
http_response_code($statusCode);
$returnedJson['error'] = $e->getMessage();
}
echo json_encode($returnedJson);
?>
This next piece of code represents the API request to restore a single record, stored in root/api/[table-name], named undelete.php:
Code:
<?php
// imports
require_once(__DIR__ . '/../../model/menu.php');
require_once(__DIR__ . '/../../service/menu.php');
require_once(__DIR__ . '/../../utilities/auth.php');
require_once(__DIR__ . '/../../utilities/controller.php');
// return headers/body
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
$returnedJson = array();
$url = 'server/api/menu/undelete.php';
$currentUserId = AuthUtility::assertUserIdInHeaders(apache_request_headers());
// check for unauthorized request
if (!ControllerUtility::assertSystemActionPermission($url, $currentUserId)) {
return;
}
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a GET request.';
echo json_encode($returnedJson);
return;
}
// check for bad request
$errors = array();
$idInRequest = ControllerUtility::isValueInRequest($_GET, 'MenuId');
if (!$idInRequest) {
http_response_code(400);
$returnedJson['error'] = 'Malformed request syntax. The following property is missing from the request: MenuId';
echo json_encode($returnedJson);
return;
}
$id = $_GET['MenuId'];
// restore the record
try {
$record = MenuService::undelete($id, $currentUserId);
http_response_code(200);
$returnedJson = $record;
}
catch (exception $e) {
$statusCode = (!($e->getCode()) ? 500 : $e->getCode());
http_response_code($statusCode);
$returnedJson['error'] = $e->getMessage();
}
echo json_encode($returnedJson);
?>
This next piece of code represents the API request to update a single record, stored in root/api/[table-name], named update.php:
Code:
<?php
// imports
require_once(__DIR__ . '/../../model/menu.php');
require_once(__DIR__ . '/../../service/menu.php');
require_once(__DIR__ . '/../../utilities/auth.php');
require_once(__DIR__ . '/../../utilities/controller.php');
// return headers/body
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');
$returnedJson = array();
$url = 'server/api/menu/update.php';
$currentUserId = AuthUtility::assertUserIdInHeaders(apache_request_headers());
// check for unauthorized request
if (!ControllerUtility::assertSystemActionPermission($url, $currentUserId)) {
return;
}
// check for bad method
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
$returnedJson['error'] = 'The supplied request method is not supported for the requested resource. This resource expects a POST request.';
echo json_encode($returnedJson);
return;
}
if (!$_POST) {
$rest_json = file_get_contents("php://input");
$_POST = json_decode($rest_json, true);
}
// check for bad request
$errors = array();
$menu = new MenuModel();
foreach (MenuModel::$RequiredColumnNames as $property) {
$success = ControllerUtility::isValueInRequest($_POST, $property);
if (!$success) {
array_push($errors, $property);
continue;
}
$menu->$property = $_POST[$property];
}
if (count($errors) > 0) {
http_response_code(400);
$returnedJson['error'] = 'Malformed request syntax. The following properties are missing from the request: ' . join(', ', $errors);
echo json_encode($returnedJson);
return;
}
// update the record
try {
$record = MenuService::update($menu->MenuId, $menu, $currentUserId);
http_response_code(200);
$returnedJson = $record;
}
catch (exception $e) {
$statusCode = (!($e->getCode()) ? 500 : $e->getCode());
http_response_code($statusCode);
$returnedJson['error'] = $e->getMessage();
}
echo json_encode($returnedJson);
?>
Last edited by dday9; Mar 8th, 2021 at 08:22 PM.
-
Mar 9th, 2021, 10:27 AM
#5
Re: [PHP] Project Architecture
Slick. MY only real gripe is the [table-name] nomenclature ... I would adopt a [object-name] instead, but that's just me.
I haven't spent too much time with the code you posted, but I don't see a whole lot wrong with it. The select * gives some pause... I see that it allows for the model to be flexible, but the DBA in me wants to throw the BS flag at that and say list out the fields, you know what's in the table.
-tg
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|