Skip to content

Instantly share code, notes, and snippets.

@charleyramm
Created June 20, 2013 14:30
Show Gist options
  • Save charleyramm/5823217 to your computer and use it in GitHub Desktop.
Save charleyramm/5823217 to your computer and use it in GitHub Desktop.
Source: http://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html Clean and simple design #HTML should look like HTML #Keep the PHP code in the views extremely simple: function calls, simple loops and variable substitutions should be all you need Secure #Input validation using pecl/filter as a data firewall #When possible, avoi…
<?php
include './ui.inc'; // Common View Helper functions
include './add_c.inc'; // Controller
head();
?>
<div id="tItems" class="ta">
<table cellspacing="0" cellpadding="3" width="100%">
<?php foreach($items as $i=>$elem) {
$s = $i%2;
echo <<<EOB
<tr id="{$elem['id']}" class="it$s">
<td>{$elem['id']}</td>
<td>{$elem['sdesc']}</td>
<td>{$elem['cat']}</td>
<td align="right">\${$elem['fprice']}</td>
</tr>
EOB;
}
?>
</table>
</div><br />
<form name="fItem" action="javascript:postForm('add.php','fItem')">
<input type="hidden" name="formName" value="fItem" />
<input type="hidden" name="id" id="f_id" value="" />
<input type="text" class="f" id="f_sdesc" name="sdesc" size="39"
maxlength="128" value="Short Description" dir="LTR" />
<select class="f" name="cat" id="f_cat" size="1">
<option selected>Category</option>
<?php foreach($categories as $cat) echo <<<EOB
<option value="{$cat}">{$cat}</option>
EOB;
?>
</select>
<input type="text" class="f" id="f_price" name="price" size="8"
maxlength="128" value="Price" dir="RTL" /><br />
<textarea style="width: 100%" name="ldesc" class="f"
id="f_ldesc" rows="5" wrap="soft">Details</textarea><br />
<input name="f_submit" type="submit" value="Add Item" />
<input type="reset" value="Clear" />
</form>
<?php
foot();
?>
<?php
include './model/db.inc';
include './model/items.inc';
$db = new items();
if($_SERVER['REQUEST_METHOD']=='POST') {
header("Content-type: application/json");
// Load an item entry from backend and send JSON request to populate form
if(isset($_POST['load_item'])) {
$entry = $db->load($_POST['load_item']);
$entry[0]['submit'] = 'Modify Item';
if($entry) echo json_encode(array('formName'=>$_POST['formName'],
'load_item'=>$entry));
exit;
}
// Validate form fields
foreach($_POST as $k=>$v) {
if(substr($k,0,5)=="desc_") {
if(isset($_POST[substr($k,5)]) && $_POST[substr($k,5)]==$v) {
echo json_encode(array('validate_error'=>'f_'.substr($k,5)));
exit;
}
}
}
// Save changes and display status message
$status = "Failure";
if($_POST['f_submit']=='Modify Item') {
$ret = $db->modify($_POST);
if($ret) $status = "Modified";
} else {
$ret = $db->insert($_POST);
if($ret) $status = "Added";
}
echo json_encode(array('status'=>$status,
'elem'=>'tItems',
'reset'=>$ret,
'formName'=>$_POST['formName']));
exit;
}
// Initialize view data
if(!isset($categories)) load_list('categories');
if(!isset($item)) $item = array('cat'=>'');
$items = $db->load();
?>
// Catch JSON replies
var fN = function callBack(o) {
myDebug(o.responseText);
var resp = eval('(' + o.responseText + ')');
if(resp['debug']) {
myDebug(resp["debug"]);
}
// Put up a Status message and fade it out
if(resp['status']) {
div = document.createElement("div");
div.className='status';
div.innerHTML = resp['status'];
pos = YAHOO.util.Dom.getXY(resp['elem']);
div.style.visibility = 'hidden'
document.body.appendChild(div);
YAHOO.util.Dom.setXY(div,[pos[0],pos[1]+40]);
div.style.visibility = 'visible'
fnc = function() {
if(resp['reset']) {
document.forms[resp['formName']].reset();
}
window.location.reload(false);
}
fade(div,2,fnc);
}
// Flash the field that had the error
if(resp['validate_error']) {
var el = document.getElementById(resp['validate_error']);
var over = el.cloneNode(true);
over.style.position = 'absolute';
over.style.zIndex=9999;
addClass(over,'error');
over.style.visibility = 'hidden'
document.body.appendChild(over);
YAHOO.util.Dom.setXY(over, YAHOO.util.Dom.getXY(el));
over.style.visibility = 'visible'
// Whoa - nested onCompletes can look a bit confusing ;)
fade(over,0.5, function() {
unfade(over,0.5, function() {
fade(over,2, function() {
over.parentNode.removeChild(over);
} );
} );
} );
}
// Fill in formName
if(resp['load_item']) {
var oForm = document.forms[resp['formName']];
for(var k in resp.load_item[0]) {
if(oForm['f_'+k]) {
if(resp.load_item[0][k].length)
oForm['f_'+k].value = resp.load_item[0][k];
else oForm['f_'+k].value = oForm['desc_'+k].value;
}
}
}
}
var callback = { success:fN }
// Post form fields from formName to target
function postForm(target,formName) {
YAHOO.util.Connect.setForm(formName);
YAHOO.util.Connect.asyncRequest('POST',target,callback);
}
function postData(target,data) {
YAHOO.util.Connect.asyncRequest('POST',target,callback,data);
}
function addClass(o,cls) {
o.className+=" "+cls;
}
function delClass(o,cls) {
o.className=o.className.replace(new RegExp(" "+cls+"\\b"), "");
}
function fade(o, dur, fnc) {
var oAnim = new YAHOO.util.Anim(o, {opacity: {from: 1, to: 0}}, dur);
if(fnc) oAnim.onComplete.subscribe(fnc);
oAnim.animate();
}
function unfade(o, dur, fnc) {
var oAnim = new YAHOO.util.Anim(o, {opacity: {from: 0, to: 1}}, dur);
if(fnc) oAnim.onComplete.subscribe(fnc);
oAnim.animate();
}
// Javascript for the item table
function clickItemPost(event) {
var target = YAHOO.util.Event.getTarget(event, true);
if(target.nodeName=='TD') target = target.parentNode;
postData('add.php','formName=fItem&load_item=' + target.id);
}
function mouseoverItem() {
this.className = 'its';
}
function mouseoutItemEven() {
this.className = 'it0';
}
function mouseoutItemOdd() {
this.className = 'it1';
}
function fancyItems() {
var oT = document.getElementById('tItems');
var oTr = oT.getElementsByTagName('TR');
for(var i=0; i<oTr.length; i++){
YAHOO.util.Event.addListener(oTr[i], "mouseover", mouseoverItem);
YAHOO.util.Event.addListener(oTr[i], "mouseout", i%2 ? mouseoutItemOdd:mouseoutItemEven);
YAHOO.util.Event.addListener(oTr[i], "click", clickItemPost);
}
}
// Javascript for the form entry section
function onfocusFormElem(event) {
var target = YAHOO.util.Event.getTarget(event, true);
var descElem = document.getElementById('desc_'+target.name);
if(document.all) { addClass(this,'iefocus') }
if(this.value == descElem.value) { this.value = ''; }
}
function onblurFormElem(event) {
var target = YAHOO.util.Event.getTarget(event, true);
var descElem = document.getElementById('desc_'+target.name);
if(document.all) { delClass(this,'iefocus') }
if(this.value == '') { this.value = descElem.value; }
}
function addHidden(oElm) {
var newE = document.createElement("INPUT")
newE.type = "hidden"; newE.value = oElm.value;
newE.name = "desc_"+oElm.name; newE.id = newE.name;
oElm.parentNode.insertBefore(newE, oElm);
}
function fancyForm() {
var oF = document.forms['fItem'];
var oElm = oF.getElementsByTagName('INPUT');
var els = oElm.length;
for(var i=0; i<els; i++) {
if(oElm[i].type != 'hidden' && oElm[i].type != 'submit' && oElm[i].type != 'reset') {
YAHOO.util.Event.addListener(oElm[i], "focus", onfocusFormElem);
YAHOO.util.Event.addListener(oElm[i], "blur", onblurFormElem);
addHidden(oElm[i]); i++; els++;
}
}
oElm = oF.getElementsByTagName('TEXTAREA');
els = oElm.length;
for(var i=0; i<els; i++) {
if(oElm[i].type != 'hidden') {
YAHOO.util.Event.addListener(oElm[i], "focus", onfocusFormElem);
YAHOO.util.Event.addListener(oElm[i], "blur", onblurFormElem);
addHidden(oElm[i]); i++; els++;
}
}
oElm = oF.getElementsByTagName('SELECT');
els = oElm.length;
for(var i=0; i<els; i++) {
if(oElm[i].type != 'hidden') {
addHidden(oElm[i]); i++; els++;
}
}
}
function myDebug(msg) {
var oDebug = document.getElementById('debug');
if(typeof(msg)=='object') {
tmp = '';
for(var i in msg) {
tmp += i + " = " + msg[i] + "<br />";
}
} else tmp = msg;
oDebug.innerHTML = [oDebug.innerHTML,tmp,'<br />'].join('');
oDebug.scrollTop = oDebug.scrollHeight * 2;
}
<?php
class db {
protected static $dbh = false;
function connect() {
self::$dbh = new PDO('sqlite:./model/example.db');
self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
protected function fatal_error($msg) {
echo "<pre>Error!: $msg\n";
$bt = debug_backtrace();
foreach($bt as $line) {
$args = var_export($line['args'], true);
echo "{$line['function']}($args) at {$line['file']}:{$line['line']}\n";
}
echo "</pre>";
die();
}
}
// load_list takes a text file and turns it into a global array cached by APC
function load_list($name) {
global $$name;
if(!$$name = apc_fetch($name)) {
$$name = explode("\n",trim(file_get_contents($name.'.txt')));
apc_store($name,$$name);
}
}
?>
<?php
/*
id INTEGER PRIMARY KEY,
cat TEXT NOT NULL,
sdesc TEXT NOT NULL,
ldesc TEXT NOT NULL,
price REAL DEFAULT 0
*/
class items extends db {
function insert($item) {
$t = $_SERVER["REQUEST_TIME"];
try {
if(!self::$dbh) $this->connect();
$stmt = self::$dbh->prepare("INSERT INTO items
(id,cat,sdesc,ldesc,price,ctime)
VALUES
(NULL,:cat,:sdesc,:ldesc,:price,$t)");
$params = array(':cat' =>$item['cat'],
':sdesc'=>$item['sdesc'],
':ldesc'=>$item['ldesc'],
':price'=>$item['price']);
$ret = $stmt->execute($params);
} catch (PDOException $e) {
$this->fatal_error($e->getMessage());
}
return $ret;
}
function modify($item) {
try {
if(!self::$dbh) $this->connect();
$stmt = self::$dbh->prepare("UPDATE items SET
cat=:cat, sdesc=:sdesc,
ldesc=:ldesc, price=:price
WHERE id=:id");
$params = array(':cat' =>$item['cat'],
':sdesc'=>$item['sdesc'],
':ldesc'=>$item['ldesc'],
':price'=>$item['price'],
':id'=>$item['id']);
$ret = $stmt->execute($params);
} catch (PDOException $e) {
$this->fatal_error($e->getMessage());
}
return $ret;
}
function load($id=-1) {
$where = '';
if($id!=-1) $where = "where id=".(int)$id;
try {
if(!self::$dbh) $this->connect();
$result = self::$dbh->query("SELECT * FROM items
$where order by ctime desc");
$rows = $result->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$this->fatal_error($e->getMessage());
}
// Some databases can do this right in the SELECT
// SQLite can't, so we add a formatted column ourselves
foreach($rows as $i=>$row) {
$rows[$i]['fprice'] = number_format($row['price'],2);
}
return $rows;
}
}
?>
<?php
function head($title="Default") { ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<title><?php echo $title?></title>
<style type="text/css" media="screen">@import "styles.css";</style>
<script type="text/javascript" src="/yui/YAHOO.js"></script>
<script type="text/javascript" src="/yui/dom.js"></script>
<script type="text/javascript" src="/yui/event.js"></script>
<script type="text/javascript" src="/yui/connection.js"></script>
<script type="text/javascript" src="/yui/animation.js"></script>
<script type="text/javascript" src="common.js"></script>
</head>
<body>
<br />
<div class="main">
<?php
}
function foot() { ?>
</div><br clear="left"/>
<font size="-1">Server -&gt; Client JSON Messages</font><br />
<div id="debug" class="debug">
</div>
<script>fancyItems(); fancyForm();</script>
</body>
</html>
<?php
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment