Welcome to the G\ Library documentation. G\ is the PHP micro-framework that takes back the fun to PHP and this documentation will teach you all you need to know to get started with G\ and start coding with it.
To begin you will need a PHP server and the G\ Library last release. We know that you are big enough to install PHP on your machine so we will skip that boring part. If you don’t know how to install PHP in your local machine you should try Wampserver (Windows) and the folks at OS X should try MAMP or just compile it. If you are using Linux or Unix you already know how to do it or at least you will know it in the next minutes thanks to Google.
G\ needs PHP 5.4+ to work and it won't work in lower PHP versions. Note that this is because in G\ we like to push PHP forward and 5.4.0 was released in March 2012, way back in time isn't?. Regarding database requirements G\ uses PDO so it will work with anything that is PDO ready.
G\ works in any PHP capable web server with URL rewriting like Apache mod_rewrite, Nginx rewriting and Lighttpd2 mod_rewrite.
In this document a few words and phrases are frequently used and you should know its meaning:
Let’s start by looking what you get once you grab G\ on GitHub.
G\ Library will be in the lib\G
folder and your application will be in the app
folder. The file that loads G\ for you app is app\loader.php
. Your app settings should be in the app\settings.php
file and your app definitions should be at app\app.php
. There are two functions files which are functions.php
and functions.render.php
, which are optional but we encourage you to use them because G\ will auto load them.
There is the app\lib
folder which includes all your app classes and third party functions. Your classes should be in the app\lib\classes
folder with the naming class.name.php
. Classes that complies with this naming will be auto-loaded by G\ and for the rest you can use the good old require_once()
function.
Finally, your themes will be in the app\themes
folder.
G\ uses a lot of helpers and definitions to make your coding an easy task. In the lib\G\G.php
you will find a lot of handly definitions like APP_PATH_CLASSES
or APP_PATH_LIB
In the lib\G\functions.php
you will find a large collection of handy functions to get and convert data like datetimegmt()
or get_client_ip()
.
There is also a file lib\G\functions.render.php
which contains functions oriented to theme display and HTML printing.
G\ app static settings should be added in the app\settings.php
file. For instance, you can set the theme doing this:
/** File: app\settings.php **/
$settings['theme'] = 'default';
The app\settings.php
file is also helpful to set anything else you may need for your app and G\ comes with a G\get_app_setting()
auxiliary function to get this values. There are a few setting keys that are reserved or perform some kind of special task. Please check the app\settings.php
file for more info.
A dynamic setting is something that should vary or be different according with other conditions. For instance, allow users to select the theme being used. In this case you should obviously store this setting in the database and to take this values into G\ you should build the $settings
global just after call G\ in the app\loader.php
file.
/** File: app\loader.php **/
// Construct the $settings global example. $db_settings was previously fetched from DB
global $settings;
$settings = array_merge($settings, $db_settings);
G\ comes with a G\DB class which is a PDO handler for database interactions. PDO (PHP data objects) is an object oriented interface that handles databases in PHP and is the actual PHP standard. G\ will warp you this PDO handler and manage the database interactions with your server. You will need to add your database details in the app\settings.php
file:
/** File: app\settings.php **/
$settings = [
'theme' => 'example', // Remember the theme right?
'db_driver' => 'mysql',
'db_host' => 'localhost',
'db_port' => '',
'db_name' => 'database_name',
'db_user' => 'database_user',
'db_pass' => ''
];
G\ will use these settings in G\DB to connect to your database.
The standard workflow of G\ is pretty simple:
app\routes\route.test.php
app\themes\<example>\test.php
G\ will bind these files to make the MVC for you. In the “Adding routes” section you will find a way to use a manually defined theme file.
Routes are one of the key elements of G\ and routes are files that bind a request to a view. Routing is how G\ handles a request like /request-name
and display an output. App routes are in the app\routes
folder and they have the route.request-name.php
naming convention. A route is a simple anonymous function:
/** File: app\routes\route.request-name.php **/
// G\ will auto include request-name.php template file for this route.request-name.php route
$route = function($handler) {
echo "hello world!";
}
The argument $handler
is the G\Handler object itself so this allows us to manipulate at our will how the G\Handler will render this route. This also helps us to access all the G\Handler methods without actually calling it, we are just defining a function that will be later on called by the G\Handler when the route is requested. Is like doing a callback.
When you create a route the system by default will ask for request-name.php
in your current theme folder, where request-name.php
comes from route.request-name.php
You skip the previous naming convention by simply using the $handler
object in your route:
/** File: app\routes\route.request-name.php **/
// G\ will include other-file.php theme file for route.request-name.php
$route = function($handler) {
echo "hello world!";
$handler->template = 'other-file';
}
You can manipulate all the instances of the G\Handler class. Try to analyse this class which is located at \lib\G\classes\class.handler.php
A sub route is something like /request-name/sub-request/etc
and sub routes basically should be handled in its parent route. G\Handler comes with handy methods that allows you to control the sub routes like for instance, allow /user/name
but not /user/name/extra
:
/** File: app\routes\route.user.php **/
// A sub route handle for /user
$route = function($handler) {
$doing = $handler->request[0]; // This gets 'name' from /user/name
/* Deny bad level request like 'user/name/extra'
user -> level 1
name -> level 2
extra -> level 3
*/
if($handler->isRequestLevel(3))) {
return $handler->issue404(); // Check "Not found (404) page" section
}
}
A query string is ?something=like-this
and G\ also allows to work with this. Certainly G\ provides you friendly URLs but in some cases a query string will suit better. Let's took an example for /request-something
route:
/** File: app\routes\route.request-something.php **/
// A query string handle for /request-something/with/?query=string
$route = function($handler) {
$doing = $handler->request[0]; // This gets 'with'
$qs = $handler->request[1]; // This gets 'query=string'
parse_str($handler->request[1], $querystr);
G\debug($querystr);
// $querystr will be an array with 'query' => 'string'
}
In the previous code G\ is handling sub routes and getting the query string for you. A little trick of G\ is that it adds the query string as a request key. Now, in your route you will be able to validate and control this query string. I recommend to use in_array()
to perform fast and safe validations in situations like this.
Not found page doesn't need a route and this view should be at app\themes\<example>\404.php
. By the way, G\ includes a method to trigger the 404 page from any line from the route:
$route = function($handler) {
return $handler->issue404();
}
By doing this you are ending the route function and triggering G\ to load the 404.php
file. This is handy when you want to deny a request if conditions are meet.
G\ Library comes ready to go with theme structure that allows you to auto connect the router with the views or template files. Your theme should be located at the app\themes\<example>
folder.
Themes works using native PHP in a very similar way of WordPress where you can use direct PHP and theme functions. The difference with WordPress is that the G\ theme functions are auto defined for each route so you don’t need to do anything else. So if in your route you do something like this:
/** File: app\routes\route.request-name.php **/
$route = function($handler) {
try {
$logged = CHV\Login::get();
$handler::$cond['admin'] = $logged['admin'] ? true : false; // Generates is_admin()
$handler::$vars['user'] = CHV\User::get($logged['id']); // Generates get_user()
} catch(Exception $e) {
G\exception_to_error($e); // G\ helper to output exeptions, log to error_log and get the trace
}
}
In the theme file connected to this route, for this example request-name.php
, the functions get_user()
and is_admin()
will return you the data populated in the route. When you use $handler::$vars['user']
the function generated will be get_user()
and it will return you the var setted in the route which could be an array, an integer and so on. When you use $handler::$cond['admin']
the function generated will be is_admin()
and it will return always boolean. Finally both functions will be ready to use in your theme file like this:
/** File: app\themes\example\request-name.php **/
<?php G\Render\include_theme_header(); ?>
// Debug the logged user only if is admin
if(is_admin()) {
G\debug(get_user());
}
<?php G\Render\include_theme_footer(); ?>
Note that the auto generated functions are only bind between one route and its view. To get a global function in all your theme files read the section "Extending".
G\ can be easily extended in the app\loader.php
file. App loader is the file used to load G\ and hook the G\Handler. This is pretty useful to alter how the G\Handler works or to set up global for all your routes. For instance, in Chevereto I needed a way to bind a few functions to all theme files so I came up with this:
/** File: app\loader.php, some bits of Chevereto loader **/
try {
$hook_before = function($handler) {
$handler::$vars['doctitle'] = get_app_setting('website_doctitle');
$handler::$vars['meta_description'] = get_app_setting('website_description');
$handler::$cond['admin'] = G\get_global('logged_user')['is_admin'] ? true : false;
};
$handy = new G\Handler(['before' => $hook_before, 'after' => NULL]);
} catch(Exception $e) {
G\exception_to_error($e);
}
Doing this is just like fooling the system with data that it should be populated on each route. In this example we added a few bindings to the router but it can be also used to manipulate the G\Handler behaviour before or after the actual request processing so you can easily extend the core routing to meet your needs, no matter if you want to add something before or at the end of the route handling.
G\ routes can be also override very easily just by adding route.name.php
In the app\routes\overrides
folder. This is perfect for those who want to add flexibility to the users of their scripts so your users can add and override your routes without touching your original routes.
G\ is not about any strict rule or coding guidelines. Go wild and code your app as you may want, G\ makes this for you incredible flexible and doesn’t bother you all because G\ always use the G namespace for its classes and functions. However, and for a best experience for you, I recommend this:
app\settings.php
to add static settings for your app like database details.app\lib\functions.php
and app\lib\functions.render.php
. G\ auto-load these files for you.app\lib\classes
folder. Classes in this folder will be auto-loaded.app\lib
folder.G\ is a non-profit project backed by my companies (Chevereto and Junkstr) and I gratefully accept any kind of help that you may want to give me like reporting bugs, fix errors, talk about G\ with your friends, etc. G\ is about making PHP more fun and for that any help is appreciated.
If you want to contribute to G\ feel free to visit G\ on GitHub.
The guy which makes this is Rodolfo Berrios, here you go. Feel free to discover my dog’s name or my other projects.
Please note that this documentation is a work in progress and your feedback is welcome.