Minggu 17 November 2019

This commit is contained in:
Damillora 2019-11-18 02:22:25 +07:00
commit 4d29a48f79
12 changed files with 233 additions and 0 deletions

59
README.md Normal file
View File

@ -0,0 +1,59 @@
# Metaforums
An online web-based discussion forum application
## Project Structure
This project is separated between the frontend and the backend application.
- backend/
The backend of this application is written in PHP, and is API focused.
- index.php
The main handler of backend functions. Handles routing, loading of Mitsumine services, and conversion of array responses to JSON.
- Mitsumine/
Mitsumine is a set of custom-written helper classes to consolidate frequently used code.
- Mitsumine/HTTP
Mitsumine HTTP contains a number of abstractions for HTTP, such as Request class
- Mitsumine/Services
Mitsumine Services contains a number of service classes for common functionality such as Database and Session.
- Application/
Application contains classes that are the core of the application itself
- Controllers/
Controllers contain controllers that return HTTP responses
- frontend/
The frontend of this application, written in HTML and utilizes T
- index.php
This index file allows serving both frontend and backend from one endpoint.
## Software Stack
The software is tested on the Apache server and PHP 7.3 on Arch Linux.
## Backend
The database used is MariaDB 10.4.8
## External frontend libraries used
### Vue.js
Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web
Vue.js allows for interactivity while being less cumbersome than manipulating the DOM manually e.g. with jQuery.
[Project Website](https://vuejs.org)
### jQuery
jQuery is a feature-rich JavaScript library.
Here, jQuery is mainly used for its AJAX functionality.
[Project Website](https://jquery.com)
## CSS Frameworks and Styles used
### Tailwind
Tailwind is a utility-first CSS framework for rapidly building custom designs
[Project Website](https://tailwindcss.com)
## Additional Development

View File

@ -0,0 +1,12 @@
<?php
namespace Application\Controllers;
use Mitsumine\HTTP\Request;
class IndexController {
public function index(Request $request) {
return [
'mitsumine' => 'yuika'
];
}
}

View File

@ -0,0 +1,6 @@
<?php
namespace Mitsumine\HTTP;
class Request {
}

View File

@ -0,0 +1,12 @@
<?php
namespace Mitsumine\Services;
class Config {
private $configs;
public function __construct() {
$this->configs = require 'backend/config.php';
}
public function __call($name, $args) {
return $this->configs[$name];
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace Mitsumine\Services;
use Mitsumine\Services\ServiceContainer;
class Database {
private $conn;
public function __construct() {
$config = ServiceContainer::Config();
$this->conn = mysqli_connect($config->db_host(),$config->db_user(),$config->db_pass(),$config->db_name());
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Mitsumine\Services;
class ServiceContainer{
private static $services = [];
public static function get($service) {
if(!isset(self::$services[$service])) {
self::load($service);
}
return self::$services[$service];
}
public static function load($service) {
$class = 'Mitsumine\\Services\\'.$service;
self::$services[$service] = new $class();
}
public static function __callStatic($name, $args) {
// Allow services to be referenced as ServiceContainer::Service()
return self::get($name);
}
}

14
backend/autoload.php Normal file
View File

@ -0,0 +1,14 @@
<?php
/*
autoload.php
Contains a simple autoloader function
*/
function mitsumine_autoloader($class) {
$file = str_replace('\\',DIRECTORY_SEPARATOR,$class);
require $file.'.php';
}
spl_autoload_register('mitsumine_autoloader');

7
backend/config.php Normal file
View File

@ -0,0 +1,7 @@
<?php
return [
'db_name' => 'metaforums',
'db_host' => '127.0.0.1',
'db_user' => 'root',
'db_pass' => '',
];

48
backend/index.php Normal file
View File

@ -0,0 +1,48 @@
<?php
require 'autoload.php';
// Use helper classes from Mitsumine
use Mitsumine\HTTP\Request;
use Mitsumine\Services\ServiceContainer;
ServiceContainer::Database();
// Get all routes
$routes = require 'routes.php';
// Get request URI
$uri = $_SERVER['PHP_SELF'];
// Cut off index.php
$uri = substr($uri,strlen('/index.php'),strlen($uri)-strlen('/index.php'));
// Build request object to pass to controller
$request = new Request();
$request_method = $_SERVER['REQUEST_METHOD'];
// Get current route from uri
$route = $routes[$request_method.':'.$uri];
// Duar (actually, split the method string to class name and method name)
$method_part = explode("@",$route['controller']);
// Get class name and method name
$class = $method_part[0];
$method = $method_part[1];
// Get fully qualified class name of route
$fqcn = 'Application\\Controllers\\'.$class;
$controller = new $fqcn();
// Execute method specified in route
$result = $controller->$method($request);
// Convert array to JSON
if(is_array($result)) {
header('Content-Type: application/json');
$result = json_encode($result);
}
echo $result;

6
backend/routes.php Normal file
View File

@ -0,0 +1,6 @@
<?php
return [
'GET:/api' => [
'controller' => 'IndexController@index',
],
];

18
frontend/index.html Normal file
View File

@ -0,0 +1,18 @@
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Yuika!'
}
})
</script>
</body>
</html>

18
index.php Normal file
View File

@ -0,0 +1,18 @@
<?php
// Get request URI
$uri = $_SERVER['PHP_SELF'];
// Cut off index.php
$uri = substr($uri,strlen('/index.php'),strlen($uri)-strlen('/index.php'));
if(strpos($uri,'/api') !== false && strpos($uri,'/api') == 0) {
include 'backend/index.php';
} else {
// Remove trailing slashes
if(substr($uri,strlen($uri)-1,1) == '/') {
$uri = substr($uri,0,strlen($uri)-1);
}
$file = 'frontend'.$uri.'.html';
if(!file_exists($file)) {
$file = 'frontend'.$uri.'/index.html';
}
readfile($file);
}