File Structure
All you need to run EMPS is a single index.php
file, a local/temp_c
folder for compiled
Smarty templates (make it writable by the server), and a local/local.php
config file for your project. A sample of the config file can be found here:
sample_local.php.
A sample of the index.php file can be found nearby:
sample_index.php.
Although the index.php
can be used as is, the local.php
file needs some editing
before it could be used.
It is preferable that the index.php
file and the local
folder (along with the
local.php
file) are located in the htdocs
subfolder of your project folder. There
could be some things that you would want to keep in your project but outside of direct
reach though the web server - those could be kept in folders other than htdocs
.
The htdocs
folder where the index.php
file is located has to be the
DocumentRoot folder of the web app that you are creating. An example of a hidden
(not directly accessible through the HTTP server)
folder would be the vendor
folder for composer components.
Or a folder to keep a nodejs app that renders your custom CSS from a SASS source.
A typical EMPS web app project folder would look like this:
{root}
- htdocs/
- local/
- temp_c/ (chmod 0777)
- index.php
- vendor/
- composer.json
Direct by HTTP(S)
Any non-PHP files that you put in the htdocs
folder are immediately accessible by the
web server for direct delivery to the end user. For example, if you want to put some images
or some CSS or JS files, you can do that by putting them to appropriate subfolders in
the htdocs
folder (don't litter in the htdocs
folder directly, though you can).
Here is how a project's htdocs
folder would look with some asset files in it:
htdocs
- css/
- design.css
- i/
- logo.svg
- background.jpg
- local/
... (appropriate files)
favicon.png
index.php
So, in this example, the /css/design.css
, /i/logo.svg
and /favicon.png
files are all
accessible directly through an HTTP(s) request to your web server, e.g.
https://my-webapp.here/i/logo.svg
. Such files are delivered directly by nginx or apache
without running any PHP code.
Extensions to EMPS File Structure
The files that constitute the source code of your web app are extensions to the folder and file structure of the base EMPS app. Those can be either new files, or files that replace the default EMPS files.
This is best understood using an example. If you create a file named
./htdocs/templates/site/headscripts.nn.htm
it will serve as a source of HTML/Smarty
template for this line of code in a core EMPS Smarty template:
templates/page/headscripts.nn.htm (follow this link to see actual EMPS6 source code)
This templates/page/headscripts.nn.htm
file is part of EMPS6/6.X, it's the default
insert that is added to the HTML code of the page inside the <head></head>
tags.
After mentioning all the standard scripts and CSS files that it has to include, it
transfers control to your project's templates/site/headscripts.nn.htm
template
that can add its own scripts and CSS files.
By default, the templates/site/headscripts.nn.htm
file does not exist in EMPS, so if you don't create it in your project, EMPS will
get an empty string when it will try to include the
{{include file="db:site/headscripts"}}
template. But,
there will be some HTML code if you define that file in your project and add some code to it.
All the static files are also treated as an extension on top of the default EMPS folder structure. For example, the EMPS file structure contains this JS file:
/js/emps.js (GitHub link)
But, if you add your own ./htdocs/js/emps.js
file to your project, you can replace
that file with your own version.
The procedure is as follows:
- A static file is first looked up in the app
htdocs
folder including the appropriate subfolders (e.g. if the request is/css/design.css
the server will first look for./htdocs/css/design.css
). - (optional step) If the file is not found in the app folder, and your app is in turn an extension to another EMPS app, the file is looked for in the parent app's folder.
- If the file is not found, it is looked up in the
EMPS6/6.5
(orEMPS6/6.0
depending on the version you are using) folder. - If the file is still not found, it is looked up in the
EMPS6/6.X
(common shared) folder. - Then, if it is not found anywhere, an HTTP/404 response is given to the client.
Automatic URL Parsing & Routing
The primary routing procedure is the following:
- The URL (the part after the hostname and before the
?
or#
) is split into parts by the slash symbol/
. So,/manage-orders/1/-/info/
becomes['', 'manage-orders', '1', '-', 'info']
. The first empty string is thrown away and what's left is['manage-orders', '1', '-', 'info']
. - The values are then assigned to EMPS variables. The following variables get extracted from a URL:
define('EMPS_URL_VARS', 'pp,key,start,ss,sd,sk,sm,sx,sy');
- In our example,
/manage-orders/1/-/info/
becomes$pp = 'manage-orders'
,$key = '1'
,$start = ''
(hypen-
means "empty value"),$ss = 'info'
. Those are actual global PHP variables, can be accessed from anywhere in subsequent PHP code. They also can be restored if you change their value and can be used to produce internal link URLs. - The module router only needs the
$pp
variable. If the value contains hypens, it replaces hypens with slashes and uses that as the local folder path, e.g.manage-orders
becomeshtdocs/modules/manage/orders
. - By default, EMPS expects to see at least an HTML template file or a PHP file in that
module folder (or both files). It assumes that the PHP script file name is the same
as the name of the last folder (in this case,
orders
) with a.php
extension. So, it looks forhtdocs/modules/manage/orders/orders.php
andrequire_once
loads that PHP script. - If the PHP script does not exist, or if it doesn't execute
$emps->no_smarty = false
, EMPS assumes that it needs to display the default Smarty template for that page. It assumes that the file name of the template is the same as the name of the folder, but with a.nn.htm
extension. You can actually have multiple templates for many languages, like.en.htm
or.ru.htm
or.it.htm
. That depends on the default language setting of the current website. But the default file is in this case -htdocs/modules/manage/orders/orders.nn.htm
. That file then gets displayed inside the Smarty template of the website (between header and footer).
Code in Modules and Referencing Include Files
Following our previous example of opening the manage-orders
URL, we now have the
orders.php
controller or procedure file and the orders.nn.htm
view file.
The PHP script can do some work and assign some Smarty variables like
$smarty->assign('order', $order)
and then the template will display {{$order.client_name}}
or {{$order.price|money}}
.
But rarely the controller or the view file can contain all the code that is needed to render this page. Sometimes they need to include some source code from another PHP file or Smarty template.
Including Files Into the Controller
-
The controller file can
require_once
orinclude
any PHP files from wherever you prefer, it can also reference autoloaded composer classes. But for referencing source files in this particular EMPS project (or default EMPS files, which are in the same virtual combined file structure, as you have learner earlier, see above) there is a special procedure to follow: -
Use the
$emps->page_file_name()
function to find the exact path to an EMPS file or a file in yourmodules
folder. -
Refer to the file using its 'virtual' name. E.g., if you want to reference a PHP class file that is contained in the
./htdocs/modules/orders/orders.class.php
file, use the this virtual name:_orders,orders.class
, i.e.require_once $emps->page_file_name('_order,orders.class', 'controller');
-
The
_
symbol specifies that the lookup function should try to find that file in themodules
folder of your app (then themodules
folder of the parent app, then the EMPS base apps, following the procedure explained above). -
The string before comma
,
specifies the path to the subfolder inmodules
, in this caseorders
means./htdocs/modules/orders/
. If there was no comma, the virtual filename parser would assume that it needed to include the file with the same name as the folder and with the extension fitting the requested file type (view
,controller
, orinc
). Controller files get the.php
extension, view files are first looked up with the.{$lang}.htm
(e.g..en.htm
) extension, and if not found - with the.nn.htm
extension. -
The string after the comma
,
, if present, specifies that the name of the include file is not the same as the name of the folder. Withview
andcontroller
types, you should omit the file extension, henceorders.class
to get theorders.class.php
file. With theinc
type, you should specify the full name of the include file.
Including Templates Into the View
- Any view file can
{{include file="..."}}
any Smarty template (HTML) inserts from other parts of the module, from other modules, other parts of HTML or even from settings (meta). - The virtual names of include files follow the same principles, in fact, the same
$emps->page_file_name()
function is used to look for the actual file (however, in this case, theview
type is used). - One important difference: the include file names in Smarty templates should start
with a prefix. The most common prefix is
db:
. When you use this prefix, the template is first looked up in the Settings (/admin-set/
page of your app), those are essentially meta variables or options. If no such setting is found, and if the virtual file name starts with a_
, then the contents is looked up using the$emps->page_file_name()
function withview
type (see above). - If the virtual file name does not start with a
_
, the file is looked up in thetemplates
folder. If it is not found there, it is looked up in the common modules folder.- (see Internal References →).
- A few quick examples:
- You can define a setting named
inc/phone
and set its value to+1 800 XXX-XX-XX
. Then, in a template, you can reference it as{{include file="db:inc/phone"}}
. - You can have a snippet of Smarty/HTML code representing a block containing, say,
product information. E.g. you have a file named
./htdocs/modules/orders/itemblock.nn.htm
. You can have it referenced from the products page by{{include file="db:_orders,itemblock"}}
. - You have a Smarty/HTML template in
./htdocs/templates/site/navbar.nn.htm
that contains some navbar code. You can reference it by{{include file="db:site/navbar"}}
. - If you need to load some HTML code into your PHP program by applying a Smarty/HTML
template, you can do it this way:
$invoice_html = $smarty->fetch("db:_orders/print,invoice");
- You can define a setting named
- More on Internal References →
The page:
Prefix for Smarty Templates
Another option to include Smarty/HTML code into your view is to create a content item
(a page) in /admin-content/
of your app. For example, you created a content item
identified by the URI _disclaimer
and used the TinyMCE editor to create some HTML
text (you can use Smarty templates there as well). This HTML code can be referenced
this way:
{{include file="page:_disclaimer"}}
.
Vue.js and Other JS Specifics, In-Browser Includes
- The Vue.js interaction works a bit differently, with a few extra steps, but
following the same principles. There, the Smarty template contains
the code that is required to load and initialize a Vue.js app or a mix-in.
The Smarty templates contain Vue.js templates (which makes an interesting and very
helpful combination of features sometimes).
And then the Vue.js
app sends requests to the
orders.php
script (or any other script for that matter) that return JSON data (no Smarty templates and no HTML). They do it by calling$emps->json_ok($data); exit;
or$emps->json_error('No such order!'); exit;
. Note that theexit
prevents any further processing and displaying of the HTML code. - The
mjs
component loader. Sometimes there are also.css
and.js
and.vue
(in EMPS,.vue
files contain only the plain HTML code of the template) files. In order to load any one of them from JS or from the template<script>
tags, use the following URL template:/mjs/{$module_pp}/{$filename}
, where{$module_pp}
is the value of the$pp
variable in the URL of this module (in our case it will bemanage-orders
), and{$filename}
is the actual file name. For example, if we also need to load the JS script for this module from this JS file -htdocs/modules/manage-orders/orders.js
we can open this external URL:/mjs/manage-orders/orders.js
. The file name can be any name, it doesn't have to match the folder name here. So it can be like/mjs/manage-orders/extra.css
.