DOCUMENTATION v1.2.0

Installation / Setup URL Routing Rendering Content Templates Handlebars Helpers HTTP Requests Cookies Data Misc Helpers

*** NOTE: This documentation is currently a work in progress. All of the information (including code samples) is current, but we're still working on the wording of everything.

...so please pardon our dust :)

INSTALLATION / SETUP

Server Requirements

  • PHP >= 5.3
  • MYSQL >= 3.0
  • Apache >= 2.4 (nginx support coming soon)
* NOTE: If you're using Coda, install the handlebars mode for syntax highlighting in your templates.

URL ROUTING

Routing with HTTP verbs

You can accept any type of http request and do things with them (really cool if you want to make an actual rest api with http verbs) (all current http verbs are supported, so you can get as specific as you want)

$app->get('/whatever/url/you/define', function(){
  // your PHP code here
});
$app->post('/whatever/url', function(){
  // your PHP code here
});
$app->post('/whatever/url', function(){
  // your PHP code here
});
$app->put('/whatever/url', function(){
  // your PHP code here
});
$app->delete('/whatever/url', function(){
  // your PHP code here
});
$app->patch('/whatever/url', function(){
  // your PHP code here
});
$app->copy('/whatever/url', function(){
  // your PHP code here
});
$app->head('/whatever/url', function(){
  // your PHP code here
});
$app->options('/whatever/url', function(){
  // your PHP code here
});

Accepting any/all matching HTTP requests

#### you can do that too (this code will run whenever you try to access this url with any kind of http request)

$app->all('/whatever/url', function(){
  // your PHP code here
});
$app->any('/whatever/url', function(){
  // your PHP code here
});

Parsing URL parameters

#### also, you can do stuff with regex or whatever to retrieve parameters from the urls. here are a few examples. see the alto router docs for more detailed info (stereo uses alto router, so you can parse the parameters in a lot of ways. here are a few examples. refer to the docs for more)

With or without the trailing slash:

$app->get('/about/?', function(){
  // your PHP code here
});

Using a url parameter as variable:

$app->get('/register/activate/[*:hash]', function($hash){ 
  // url parameter is available to your PHP code as $hash
});

And of course you can access _GET vars like normal PHP docs:

$app->get('/directory/search/?', function(){ 
  // ex url: http://partyphysics.com/directory/search/?fish=betta&dish=espinacas&planet=keppler-452b
  echo $_GET['fish'];  // betta
  echo $_GET['dish'];  // espinacas
  echo $_GET['planet'];  // keppler-452b
});

RENDERING CONTENT

########### once you have a URL route set up, it's a good idea to define what happens there. the sky is almost the limit for what you can do at that point...it just has to be php. here are some cool options!

render_template ($options)

Render a handlebars template with special STEREO abstraction variables ()

$app->get('/handlebars-stereo', function(){
  $GLOBALS['app']->render_template(array(
    'template' => 'planets',
    'title' => 'Cool Planets',
    'layout' => false,
    'data' => array(
      'righteous_content' => 'for_sure',
      'planets' => array(
        'Mercury', 'Venus', 'Earth', 'Nibiru'
      )
    )
  ));
});

render_json ($options)

Render an array of data as a JSON string and send with JSON headers (handy for easily making API responses)

$app->post('/json-response', function(){
  $GLOBALS['app']->render_json(array(
    'righteous_content' => 'for sure',
    'planets' => array(
      'Mercury', 'Venus', 'Earth', 'Nibiru'
    )
  ));
});

render ($template_name, $data)

Render a handlebars template using a php array for saturation (note this is not attached to the stereo $app class)

$app->get('/handlebars-normal', function(){
  echo $GLOBALS['engine']->render('handlebars-example', array(
    'righteous_content' => 'for sure',
    'planets' => array(
      'Mercury', 'Venus', 'Earth', 'Nibiru'
    )
  ));
});

Show a document at a given url

want to show just a document? do it like this

$app->get('/normal-page', function(){
  require __DIR__ . '/pages/whatever.html';
});

Send headers

send a header. it can be whatever you want...this is nothing special with the framework, just something good to remember

$app->get('/whatever', function(){
  header("Location: http://partyphysics.com/");
});

TEMPLATES

########### something something templates go in ./pages and you can call them whatever you want. you can organize this however you want, too! link to handlebars docs for more info.

Basic Variables

#### the simplest thing to do. if you use render_template, stereo includes a few by default (year, etc) as well as a few special things (is_admin, auth, user_id, etc) (title [uses the site title by default, so it's kinda optional])

### php

$app->get('/variable-example', function(){
  $GLOBALS['app']->render_template(array(
    'template' => 'demo',
    'data' => array(
      'fish' => 'salmon',
      'dish' => 'paella',
      'planet' => 'Nibiru'
    )
  ));
});

### hbs (note about literals { { { } } } vs { { } } -- by default hbars doesn't parse html tags, so if you want to have them rendered, do this)

<h2>Simple Variables Example</h2>
<h3>Cool Fish: {{fish}}</h3>
<h3>Cool Dish: {{dish}}</h3>
<h3>Cool Planet: {{planet}}</h3>

Iterating Arrays

### it's hella easy, just like a foreach loop. you can even nest the arrays to infinity (and beyond) (sorry) (it can be as simple or complex as you want to make it) (see the demo controller/templates for an example of more complex array iteration)

### php (simple & complex example from demo)

$app->get('/array-example', function(){
  $GLOBALS['app']->render_template(array(
    'template' => 'demo',
    'data' => array(
      'snacks' => array(
        'Carrots',
        'Hay',
        'Sugar Cubes',
        'Oats',
        'Apples',
        'Weaker Horses'
      )
    )
  ));
});

### hbs (simple & complex example from demo)

<ul>
  {{#each snacks}}
  <li>{{this}}</li>
  {{/each}}
</ul>

Simple Logic

you can do some simple logic to check if a variable exists (or has value). if you would like to do more complex logic, check out [if_either], [in_array], [is]

### php

$app->get('/logic-example', function(){
  $GLOBALS['app']->render_template(array(
    'template' => 'demo',
    'data' => array(
      'fish' => 'salmon',
      'dish' => 'paella',
    )
  ));
});

### hbs (if/else, unless, (normal hbars logic, link to hbars docs) maybe is & link to helpers)

{{#if fish}}
 Salmon is available
{{else}} // this won't show:
 No salmon for you.
{{/if}}

{{#unless snacks}}
 No snacks available. We have {{dish}}, though.
{{else}} // this won't show:
 Look at all the snack options:
 {{#each snacks}}
 - {{this}} <br />
 {{/each}}
{{/unless}}

Partials

### You can include templates in other templates! That is neat! all your partials need to be in the _partials directory, but you can organize that however you want!

### normal php whatever example

$app->get('/partials-example', function(){
  $GLOBALS['app']->render_template(array(
    'template' => 'demo',
    'data' => array(
      'fish' => 'salmon',
      'dish' => 'paella',
      'planet' => 'Nibiru'
    )
  ));
});

### hbs

<h2>Demo page (rendered with partial from separate template)</h2>

<h3>Fish: {{fish}}</h3>
<h3>Dish: {{dish}}</h3>

{{> planets-partial}}

### hbs (partial code) (see how it has access to the same data?)

<ul>
  {{#each planets}}
  <li>{{this}}</li>
  {{/each}}
</ul>

Global Layouts

### if you want to use a global header footer, you can! you can define as many global wrappers/layouts as you want (like express, django, ember, whatever...wow!) if you leave the "layout" parameter blank, STEREO will use the layout in ./pages/_layouts/base.hbs by default. your content will be rendered where the [[outlet]] part is

### php example

$app->get('/layouts-example', function(){
  $GLOBALS['app']->render_template(array(
    'template' => 'demo',
    'title' => 'Site Title Whatever',
    'layout' => 'admin',  // false for nothing, base by default
    'data' => array(
      'fish' => 'salmon',
      'dish' => 'paella',
      'planets' => array(
        'Mercury', 'Venus', 'Earth', 'Nibiru'
      )
    )
  ));
});

### hbs (wrapper)

<!DOCTYPE html>
<html>
<head>
  <title>{{title}}</title>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1" />
  <link rel="stylesheet" href="/css/app.css" />
</head>
<body>

  <div class="header"><h1>Site Title Whatever</h1></div>

  <div class="container">
    [[outlet]]  // this is where the content will be rendered
  </div>

  <div class="footer">(c) {{year}} -- All rights reserved or whatever.</div>

<script src="/js/vendor/jquery.min.js"></script>
<script src="/js/app.js"></script>

</body>
</html>

### hbs

<h2>Demo page (rendered with global wrapper)</h2>

<h3>Fish: {{fish}}</h3>
<h3>Dish: {{dish}}</h3>

<ul>
  {{#each planets}}
  <li>{{this}}</li>
  {{/each}}
</ul>

Template Locals (Global Variables)

### need to make an arbitrary variable/array available to all the templates? use $GLOBALS['locals'] (hold for laugh) but seriously, folks, treat it like an array and whatever you need. and if it's an array is something you can iterate over. and, of course, all of this is available to the application as $GLOBALS['locals']['numbers'] or whatever

### php example

$GLOBALS['locals']['eat_this'] = "breakfast";

### hbs

Let's have {{locals.eat_this}} for dinner.

### php example

$GLOBALS['locals']['colors'] = array('red', 'salmon', 'lilac', 'azul');

### hbs

<ul>
  {{#each locals.colors}}
  <li>{{this}}</li>
  {{/each}}
</ul>

HANDLEBARS HELPERS

#### You can use handlebars helpers to transform any of your handlebars variables. STEREO includes a handful of common php functions as helpers plus a few special ones. you can write your own, too! it's super easy!

lowercase

#### transform string to lowercase (link to php docs)

{{lowercase hbar_variable}}
// "Don't Fear The Reaper"   --->   "don't fear the reaper"

addslashes

#### escape quotes (link to php docs)

{{addshlashes hbar_variable}}
// "Don't Fear The Reaper"   --->   "Don\'t Fear The Reaper"

nl2br

#### note u gotta use 3 curly braces w/ this because it turns plain text to html just F Y I// nl2br // transform line breaks to "br /" ()link to php docs

{{{nl2br hbar_variable}}}
/* 
   
"Don't Fear The Reaper"
 
--->
 
"Don't Fear <br /> The Reaper"
*/

to_fixed

#### // to_fixed // return given number calculated to given number of decimal places (defaults to 2)

{{to_fixed hbar_variable}}    // 3.14
{{to_fixed hbar_variable 4}}  // 3.1415
{{to_fixed hbar_variable 0}}  // 3

date

#### parse unix timestamp into human-readable date format (basically php's date()). use "now" for current date/time

{{date hbar_variable "m/d/Y"}}  // "1459036800"   --->   "3/27/2015"
{{date "now" "m/d/Y"}}  // "11/16/2018"

date_transform

#### transform time/date format (same as date, but it turns a string [like a js date object] into unix time first)

{{date_transform hbar_variable "m/d/Y"}}  // "Sun Aug 14 2016 00:00:00 +0000"   --->   "8/14/2016"

in_array

####// in_array // return true(/false) if this item is(/is not) in the array // // can be a csv string, too

/*
  colors_array = ['red', 'salmon', 'lilac', 'azul']
                    -- or --
  colors_array = "red, salmon, lilac, azul"
*/

{{#in_array colors_array "spectral-green"}} 
 it's in the array!
{{else}} 
 it's not in :(
{{/in_array}} 
		

if_either

####// if_either // return true if the first thing equals either the second or third thing (they could also be hbar_variables)

{{#if_either hbar_variable "salmon" "azul"}}
 it's true :)
{{else}}
 it's false :(
{{/if_either}}

is

#### this one has a lot of cool options // is // basic comparison operators you can compare either hbars variables or strings (and use arrays, in some cases) acceptable operators: ==, ===, not, !=, <, >, <=, >=, in, typeof

{{#is hbar_variable "==" "paella"}}
 yes :)
{{else}}
 no :(
{{/is}}

// will also show if the first thing is contained within the second thing (even it's CSV) (2nd thing can be a string, csv list, or an array) // 2nd param can beither array or csv

{{#is hbar_variable_1 "in" hbar_variable_2}}
 yes :)
{{else}}
 no :(
{{/is}}

// you can also compare variables by types (array, string, integer, etc) (uses php gettype: http://php.net/manual/es/function.gettype.php)

{{#is hbar_variable_1 "typeof" hbar_variable_2}}
 yes :)
{{else}}
 no :(
{{/is}}

Custom Helpers

### it's easy, just write a php function and put it in ./controllers/_global.php and then use it in whatever template. look! (you can copy this code as a good starting point). here's a simple example combining a couple simple native php functions. take a look at the handlebars-helpers file to see more examples of how we put together the more complex helpers (we got a lot of these from somewhere, anyone remember where?)

### php example

$engine->addHelper('lowercase_slashes', function($template, $context, $args, $source) {
  $parsed_args = $template->parseArguments($args);
  return lowercase(addslashes($context->get($parsed_args[0])));
});

### corresponding hbs (wrapper)

{{lowercase_slashes hbar_variable}}
// "Don't Fear The Reaper"   --->   "don\'t fear the reaper"

HTTP REQUESTS

##### something something it's trivially easy to work with other systems if you use an api! look how easy it is to consume 3rd-party services - a lot of times you might have a need to integrate things you've made with other systems. fortunately, everyone can consume/produce json apis and this is perfect.

http_request ($url, $data)

Make an http request to a given url (using curl), send data, return the raw response.

$data = $GLOBALS['app']->http_request('https://external-api.com/v3/example-response', array(
  'user_id' => 581146,
  'api_key' => '696719xvckvzxspigh24y1e-b'
));

json_request ($url, $data)

Make an http request to a given url, send data, and return an array of response data (expects response in json format...like the kind sent from render_json). (append _debug to just make an http request and see the raw result)

$data = $GLOBALS['app']->json_request('https://external-api.com/v3/example-response', array(
  'user_id' => 581146,
  'api_key' => '696719xvckvzxspigh24y1e-b'
));

/* expected response: 
  {
    first_name: "Eddie",
    last_name: "Mercury",
    favorite_fish: "Salmon"
  }
*/

print_r($data);

/* 
  array(
    'first_name' => 'Eddie',
    'last_name' => 'Mercury',
    'favorite_fish' => 'Salmon'
  );
*/

api_request ($url, $data)

Make a json request to a given url, send hard-coded data from cookies (user_id, auth_token, admin_token, moderator_token). Specialized for use with STEREO patterns/components (coming soon) -- // same as json_request, but in addition to data params, this sends the user_id, auth_token, admin_token, moderator_token set in cookies as those params, uses the $GLOBALS['api_root'] in settings. you can set extra variables to send (like if your api requires a key or whatever...see stereo-core.php, the function called "api_request" obv) (append _debug to just make an http request and see the raw result)

$data = $GLOBALS['app']->api_request('/admin/events/screen', array(
  'parameter_1' => 'cool stuff',
  'parameter_2' => 'cooler stuff'
));

/* data sent to api would look something like:
  {
    user_id: "581146",
    admin_token: "123123-1230973t2097sdv",
    auth_token: "1203920rdvslasphwg",
    moderator_token: false,
    parameter_1: "cool stuff",
    parameter_2: "cooler stuff"
  }
*/

/* expected response: 
  {
    first_name: "Eddie",
    last_name: "Mercury",
    favorite_fish: "Salmon"
  }
*/

print_r($data);

/* 
  array(
    'first_name' => 'Eddie',
    'last_name' => 'Mercury',
    'favorite_fish' => 'Salmon'
  );
*/

COOKIES

###########

cookie_set ($key, $value, $expiration_date)

Set a cookie for a given amount of time.

$GLOBALS['app']->cookie_set(
  'user_name',
  'Buzz',  // can be a string or an array or whatever
  1461619625  // optional, in unix time format, default is time() + 31536000000
);

cookie_get ($key)

Return the value of a given cookie.

echo $GLOBALS['app']->cookie_get('user_name');  // Buzz

cookie_delete ($key)

Delete a given cookie.

$GLOBALS['app']->cookie_delete('user_name');

DATA

########### (something mysql crud functionality, requires pdo (php 5.3+), global functions, not part of the $app class, so use it however it suits you)

db_insert ($table, $input)

Sanitize parameters and insert array of data into database. Returns the id of the record created.

$new_id = db_insert("celestial_bodies", array(
  'name' => 'Luna',
  'classification' => 'moon',
  'comment' => 'Earth\'s moon, also commonly referred to as "the moon"'
));

echo $new_id;

db_find ($table, $criteria, $options)

Sanitize parameters and retrieve data from database. (SELECT *)
Returns an array with the the data and a total number of results.

$planets = db_find("celestial_bodies", "classification = 'planet' ORDER BY title ASC LIMIT 8");

foreach ($planets['data'] as $p){
  echo $p['title'];
  echo $p['classification'];
  // etc, etc
}

echo $planets['total'];  // 8

You can run a raw query (if you need to do joins or anything fancy)

$space_objects = db_find("", "SELECT title, classification FROM celestial_bodies WHERE id IS NOT NULL", array(
  'raw' => true
));

If APC is enabled on your system, you can cache your queries

$planets = db_find("celestial_bodies", "classification = 'planet' ORDER BY title ASC", array(
  'cache' => true,
  'cache_length' => 120  // optional, in seconds, default is 60
));

db_update ($table, $input, $criteria)

Sanitize parameters and update a database record.

db_update("celestial_bodies", array(
  'name' => 'Mars',
  'comment' => 'Research "The Phobos Incident" -- we are not alone'
), "name='Marz'");

db_delete ($table, $criteria)

Sanitize parameters and delete a given database record.

db_delete("celestial_bodies", "name='venice'");

MISC HELPER FUNCTIONS

###########

email_send ($options)

Send an plain text or html email (with mailgun api, if available, otherwise using php mail).

$GLOBALS['app']->email_send(array(
  'to' => 'static@hexgirlfriend.com',
  'from' => 'sitemeister@partyphysics.com',
  'cc' => 'cc-address@partyphysics.com',  // optional
  'bcc' => 'bcc-address@partyphysics.com',  // optional
  'reply-to' => 'reply-address@partyphysics.com',  // optional
  'subject' => 'Send me an email',
  'html' => true,  // optional, message will be sent as plain text unless this is true
  'message' => 'Right now...<br /><br /><br /><b><u>RIGHT NOW</u></b>'
));

client_ip ()

Return the address of the computer making the current request.

echo $GLOBALS['app']->client_ip();
more of these: url_slug url_strip url_validate mysql_date video_id br2nl pagination_query pagination_links