Php +framework7 => web app?

I try to build (php(codeigniter) + framework7) web app.
Also, I cannot use webpack and npm in my server with some reasons.

I made url like “www.servicename.com/app”,
and then I started to develop web app with framework7.

Not only I use php for api, but also I made pages(url) using php.
(example)
www.servicename.com/app/pageA
www.servicename.com/app/pageB
www.servicename.com/app/pageC

In framework7 router,
I access page with url like ‘/pageA’
,page with url like ‘/pageB’
,page with url like ‘/pageC’

questions

  1. is this right way to build with php + framework7?
  2. In the main-home(index.html), can i use componenturl style?

i tried my best to solve my basic setting, but I could find any way to forward.

Thank you for reading,
and Thank you framework7 users!

I also use php and f7 but i use php just as an API providing json data
and use ajax requests to access the data

I heard often that one shouldn’t use php for REST API especially when you are making chat applications but its what i can work with and also big players like facebook use php and can get along with it :slight_smile:

2 Likes

Thank you so much Momo!!

Then, how can you start f7?

I mean,
if i use php only for api,
isn’t there any server prepared for f7?
or
do I have wrong concept about web app?

I thought f7 web-app needs server setting like web page.

I have built for myself a little library which i use because i couldn’t find something simple its quite flexible and this is the code for it:

API.class.php

<?php 

	abstract class API
	{
		/**
		 * Property: method
		 * The HTTP method this request was made in, either GET, POST, PUT or DELETE
		 */
		protected $method = '';
		/**
		 * Property: endpoint
		 * The Model requested in the URI. eg: /files
		 */
		protected $endpoint = '';
		/**
		 * Property: verb
		 * An optional additional descriptor about the endpoint, used for things that can
		 * not be handled by the basic methods. eg: /files/process
		 */
		protected $verb = '';
		/**
		 * Property: args
		 * Any additional URI components after the endpoint and verb have been removed, in our
		 * case, an integer ID for the resource. eg: /<endpoint>/<verb>/<arg0>/<arg1>
		 * or /<endpoint>/<arg0>
		 */
		protected $args = Array();
		/**
		 * Property: file
		 * Stores the input of the PUT request
		 */
		 protected $file = Null;

		/**
		 * Constructor: __construct
		 * Allow for CORS, assemble and pre-process the data
		 */
		public function __construct($request) {
			header("Access-Control-Allow-Orgin: *");
			header("Access-Control-Allow-Methods: *");
			header("Content-Type: application/json");

			$this->args = explode('/', rtrim($request, '/'));
			$this->endpoint = array_shift($this->args);
			if (array_key_exists(0, $this->args) && !is_numeric($this->args[0])) {
				$this->verb = array_shift($this->args);
			}

			$this->method = $_SERVER['REQUEST_METHOD'];
			if ($this->method == 'POST' && array_key_exists('HTTP_X_HTTP_METHOD', $_SERVER)) {
				if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'DELETE') {
					$this->method = 'DELETE';
				} else if ($_SERVER['HTTP_X_HTTP_METHOD'] == 'PUT') {
					$this->method = 'PUT';
				} else {
					throw new Exception("Unexpected Header");
				}
			}

			switch($this->method) {
			case 'DELETE':
			case 'POST':
				$this->request = $this->_cleanInputs($_POST);
				break;
			case 'GET':
				$this->request = $this->_cleanInputs($_GET);
				break;
			case 'PUT':
				$this->request = $this->_cleanInputs($_GET);
				$this->file = file_get_contents("php://input");
				break;
			default:
				$this->_response('Invalid Method', 405);
				break;
			}
		}
		
		public function processAPI() {
			if (method_exists($this, $this->endpoint)) {
				return $this->_response($this->{$this->endpoint}($this->args));
			}
			return $this->_response("No Endpoint: $this->endpoint", 404);
		}

		private function _response($data, $status = 200) {
            if($data === NULL)
                return ;
            else {
                header("HTTP/1.1 " . $status . " " . $this->_requestStatus($status));
                return json_encode($data);
            }
		}

		private function _cleanInputs($data) {
			$clean_input = Array();
			if (is_array($data)) {
				foreach ($data as $k => $v) {
					$clean_input[$k] = $this->_cleanInputs($v);
				}
			} else {
				$clean_input = trim(strip_tags($data));
			}
			return $clean_input;
		}

		private function _requestStatus($code) {
			$status = array(  
				200 => 'OK',
				404 => 'Not Found',   
				405 => 'Method Not Allowed',
				500 => 'Internal Server Error',
			); 
			return ($status[$code])?$status[$code]:$status[500]; 
		}
	}
?>

api.php

<?php 
	//error_reporting(E_ERROR | E_WARNING | E_PARSE);
    error_reporting(E_ALL);
    //error_reporting(E_ERROR | E_PARSE);
    //ini_set('display_errors', 'on');
    ini_set('display_errors',1);

    set_time_limit(30); 
	date_default_timezone_set('Europe/Vienna');
	
	require_once 'libs/MysqliDb.php';
	require_once 'libs/dbObject.php';
    require_once 'libs/php-ml/vendor/autoload.php'; 
	
	require_once 'endpoint.class.php';
	
	
	
	define('ROOT',realpath(dirname(__DIR__)).DIRECTORY_SEPARATOR);
	// Allow from any origin
	if (isset($_SERVER['HTTP_ORIGIN'])) {
		// Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one
		// you want to allow, and if so:
		header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
		header('Access-Control-Allow-Credentials: true');
		header('Access-Control-Max-Age: 86400');    // cache for 1 day
	}
	
	// Access-Control headers are received during OPTIONS requests
	if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

		if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
			// may also be using PUT, PATCH, HEAD etc
			header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

		if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
			header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

		exit(0);
	}
	if($_SERVER['REMOTE_ADDR'] == "127.0.0.1") {
		// Initiate Database Connection
		$db = new MysqliDb (Array (
                'host' => 'localhost',
                'username' => 'root', 
                'password' => '',
                'db'=> '',
                'charset' => 'utf8mb4'));
	} else {
		$db = new MysqliDb (Array (
                'host' => 'localhost',
                'username' => '', 
                'password' => '',
                'db'=> '',
                'charset' => 'utf8mb4'));
	}
	
	dbObject::autoload();

	// Requests from the same server don't have a HTTP_ORIGIN header
	if (!array_key_exists('HTTP_ORIGIN', $_SERVER)) {
		$_SERVER['HTTP_ORIGIN'] = $_SERVER['SERVER_NAME'];
	}

	try {
		$API = new endpoint($_REQUEST['request'], $_SERVER['HTTP_ORIGIN']);
        echo $API->processAPI();
	} catch (Exception $e) {
		echo json_encode(Array('error' => $e->getMessage()));
	}
?>

endpoint.class.php

<?php
    //TODO Unified Account lookup

    //define("PROTOCOL", strtolower(substr($_SERVER["SERVER_PROTOCOL"],0,strpos( $_SERVER["SERVER_PROTOCOL"],'/'))).'://');

	require_once 'API.class.php';
	require_once 'Models.APIKey.class.php';

	class endpoint extends API
	{
		const API_ACCESS_KEY = 'AIzaSyCA50FSHQXYIa';
		protected $user;

		public function __construct($request, $origin) {
			parent::__construct($request);

			// Abstracted out for example
			$APIKey = new Models\APIKey();

			if (!array_key_exists('key', $this->request)) {
				throw new Exception('NoAPIKeyProvided');
			} else if (!$APIKey->verifyKey($this->request['key'], $origin)) {
				throw new Exception('InvalidAPIKey');
			}
			if (array_key_exists('token', $this->request)) {
                //Check token if valid
                } else {
					throw new Exception('LogIn');
				}
			}
            /*
            if(array_key_exists('version', $this->request)) {
                
            } else {
                throw new Exception('DeprecatedVersion');
            }*/
		}
	//endpoint login
	protected function login() {
	return false
	}
?>

in endpoint.php you can add your endpoints which do all the logic
and the last piece is the htaccess file:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule v1/(.*)$ api.php?request=$1 [QSA,NC,L]
</IfModule>

when you do an ajax request to an endpoint this is how the url can look like:

https://api.domain.com/v1/login?key=AIzaSyCA50FSHQXYIa&name=momo&password=123321

login is the in this case the endpoint, it can also be called by using the request query

the queries name & password will popup in the $this->request variable within our endpoint class

all functions in the endpoint class can return values which will automaticly translated into json hope that helps if you have any improvements or suggestions I would love to hear and get aswell! :slight_smile:

this is just an example so dont take it seriouse obviously you shouldnt send your user password around like that haha

its fairly simple but works

3 Likes

Thank you so much! Momo

I would study about your example,
and try my best to get answer in there.

Again, Thank you so so much, my hero!

Hey - great… I’d like to use this for a simple prototype… where are the required libs from?

You are talking about that? you don’t need them, php-ml is a machine learning library if you google it you will finde it, and Mysqli https://github.com/ThingEngineer/PHP-MySQLi-Database-Class if you want to use it

Why not use a minimal framework like https://lumen.laravel.com/ ?

Its fast and has a large community developing, and security is peer- reviewed.

The code suggested on this thread seems very similar (equal ) to the one found here .

I would advise not to rely on variables that come within the Headers’ request sent by client. They’re easily spoofed.

Others solutions here

Framework7 mobile app tutorials: https://www.youtube.com/playlist?list=PLSDxfTZT8FU6hG1SA_A9YlEHp8R2qRqBx

its based on this code there, I tried to change my post to add the link because initial I couldn’t find the post, I have done some minor changes to allow also different response than just json

Hello, everyone!
Thanks to this discussion, I can improve my own way to develop Codeigniter + framework7

Now I made new kinds of prototype with framework7 and codeigniter,
So, If anyone wants to know new way I made,
let me know or message to me.

It would be weired way to use framework7 and codeigniter together
but now i am really satisfied

Thank you everyone,
and thank u framework7

Here is another solution, using f7 with react and php backend… maybe a good starting point for someone.

it can be good choice for people!
Thank you for letting me know this