Lately I’ve created a variety of projects and I’ve modified my command structure just slightly.  This new method has a couple minor advantages, but still utilizes the essentials of the command structure.

The overall file structure of a project looks something like this:

  • common.inc.php
  • header.inc.php
  • footer.inc.php
  • classes/class.inc.php
  • view.php
  • c_controller.php

In the new view.php and c_controller.php files, I’m still using my command structure, but the controller is contained (more or less) exclusively within the c_controller.php file.  This lets me include only the common file (instead of the header which then includes the common file), and lets me have a nice redirect statement at the bottom of the file to redirect back to wherever the user was before the controller was called, which makes the code even more easily reusable.

common.inc.php

This is the core file that allows your entire system to run.  Includes to autoloaders, globals, settings, required functions, etc., all live here.

header.inc.php

This file generally starts with an include to the common.inc.php file, then starts building out the beginning of the HTML.  That includes includes for javascript and css files as well as either housing the nav directly in this file, or if it’s more complex (or variable), includes the nav as necessary.  The view.php page that includes this header.inc.php file can also set various variables which are examine here such as $login_required or $use_ck_editor.

footer.inc.php

Closes up the header’s HTML, might append memory usage or page run-time statistics if needed or desired.

classes/class.inc.php

I generally have one class file per MySQL table plus other classes for significant object-oriented functions.  UI, string, array, and date object classes can all live in here as well.  Example filenames might be user.inc.php, job.inc.php, company.inc.php.

view.php

This will display whatever content you’re trying to show to the user.  It can optionally use the command structure as well.  Typically this is some kind of a list-of-elements page, or a view-detail or edit-item page.  Example file names might be users.php, user.php, jobs.php, job_edit.php, etc.

c_controller.php

This is generally executed from buttons or links clicked on view.php pages, will process some kind of work, and redirect the user back to a view.php page.  This file always uses the command structure so that multiple control segments can live within a single file.  If the user needs to land on a particular page, that can be specified in the command segment, or the specified landing page can be omitted and the script will redirect the user back to the page they were previously on.  Example file names might be c_user.php, c_job.php, c_company.php, etc.

September 22nd, 2015

Posted In: Uncategorized

Leave a Comment

After banging my head on the desk for far longer than I’d like to admin, I finally figured out the really simple reason my installation of a SSL certificate on a Amazon Linux EC2 instance wasn’t working: Apache has a separate config file for SSL information that is not in the standard /etc/httpd/conf/httpd.conf file.

It’s in /etc/httpd/conf.d/ssl.conf.

Many many thanks to http://jafty.com/blog/installing-godaddy-ssl-certificate-on-amazon-ec2/ for pointing me in the right direction!

Also, just as a reminder for myself, if you’re using a GoDaddy-based SSL certificate that has the “bundle.crt” file, use the SSLCACertificateFile not the SSLCertificateChainFile option in the ssl.conf file.

May 7th, 2015

Posted In: Uncategorized

Leave a Comment

We’re all familiar with MVC.  Model, view, controller.  What if it should actually be MSVC?  Model, Security, View, Controller?

Here’s what I’m thinking: In traditional MVC, the question of where to put in security is vague.  The worst security may be applied at the view layer, but anyone that knows how to hack around a web form can probably bypass it.  Controller-based security would work better, but what if you have a complex security-permissions system?  Adding it at the Model level probably doesn’t give you enough context to understand whether or grant the request or not.

So I’m thinking, insert a layer above the model, below the controller that’s “Security/Permissions”.  The model would pass it’s data and requests to the security system, which if approved, would be passed to the model.  If permission is not granted, the security layer can pass back various complaints to the controller which will then display those in the view.

I doubt I’ll have an opportunity to try writing a project using this idea anytime soon, but I wanted to get it down on “paper” while it was still fresh.

August 13th, 2014

Posted In: Uncategorized

Leave a Comment

The dateFormat function is one that I love. Throw any kind of date format at it, request any format back, it just works.

Examples of usage:

$humanDisplay = dateFormat('2013-08-22 17:52:33','human');
$tomorrow = dateFormat('now + 1 day','human');
$mysql_date = dateFormat('8/30/2013','mysqldate');
$mysql_datetime = dateFormat('8/30/2013 5:00 PM','mysql');
$unix_timestamp = dateFormat('8/30/2013 5:00 PM','php');

if(dateFormat('now','php')>dateFormat($someVariable,'php')) {
// do stuff
}

The dateFormat function (and related supporting functions):

function parseTimezone($inputDate) {
	if(	   strpos($inputDate,'Eastern')>0
		|| strpos($inputDate,'Central')>0
		|| strpos($inputDate,'Mountain')>0
		|| strpos($inputDate,'Pacific')>0
		|| strpos($inputDate,'Alaska')>0
		|| strpos($inputDate,'Hawaii-Aleutian')>0
		|| strpos($inputDate,'Arizona')>0 
		|| strpos($inputDate,'America/')>0 
		|| strpos($inputDate,'Pacific/')>0 
		|| strpos($inputDate,'GMT')>0
		) {
		$parts = explode(' ',$inputDate);
		$timezoneName = array_pop($parts);
		$inputDate = implode(' ',$parts);
	}
	return $inputDate;
}


function isValidDate($inputDate) {
	if($inputDate=="01/01/0001"
		|| $inputDate=="01/01/01"
		|| $inputDate=="0001-01-01"
		|| $inputDate=="0000-01-01"
		|| $inputDate=="0000-00-00"
		|| $inputDate==""
		|| strlen($inputDate)<3
		) {
		return false;
		// don't increase the required length by more than 3 so "now" doesn't get cut
	}
	
	$inputDate = parseTimezone($inputDate);
	
	
	if(is_numeric($inputDate) && $inputDate>100000000) {
		// 100000000 = 1973-03-03 01:46:40
		// this should catch all integers that are errantly caught as dates
		$phpTime = $inputDate;
	} elseif($inputDate!='' && ( strpos(strtolower($inputDate),'now')!==false 
									|| strpos($inputDate,'/') 
									|| strpos($inputDate,'-')
									|| strpos($inputDate,'day')
									|| strpos($inputDate,'week')
									|| strpos($inputDate,'month')
									|| strpos($inputDate,'year')
									) ) {
		$phpTime = strtotime($inputDate);
	} else {
		return false;
	}
	
	if($phpTime==-62135568000) { // 0000-00-00
		return false;
	}
	if($phpTime==NULL) {
		return false;
	}
	$month = date('n',$phpTime);
	$day = date('j',$phpTime);
	$year = date('Y',$phpTime);
	
	return checkdate($month,$day,$year);
}


function dateFormat($inputDate, $format=NULL, $params=array()) {
	if(!isValidDate($inputDate)) {
		$inputDate=NULL;
	}
	if(strtolower($inputDate)=="now" || strtolower($inputDate)=="now()") {
		$inputDate = "now";
	}
	if($format==NULL) {
		$format="human";
	}
	
	$inputDate = parseTimezone($inputDate);
	
	if(is_numeric($inputDate) && (int)$inputDate==$inputDate) {
		$phpTime = $inputDate;
	} elseif($inputDate!='') {
		$phpTime = strtotime($inputDate);
	}
	
	if($phpTime) {
		if($format=="human") {
			return date("m/d/Y",$phpTime);
		} else if(strtolower($format)=="mysql") {
			return date("Y-m-d H:i:s",$phpTime);
		} else if(strtolower($format)=="mysqldate" || ($format=="%Q") ) {
			return date("Y-m-d",$phpTime);
		} else if(strtolower($format)=="mysqltime" || ($format=="%T") ) {
			return date("H:i:s",$phpTime);
		} else if(strtolower($format)=="solr") {
			return gmdate('Y-m-d\TH:i:s\Z',$phpTime);
		} else if(strtolower($format)=="php") {
			return $phpTime;
		} else if(strtolower($format)=="human datetime") {
			return date("n/j/y g:i A",$phpTime);

		} else if($format!='') {
			return date($format,$phpTime);
		}
	} else {
		return NULL;
	}
}

September 13th, 2013

Posted In: Functions

Leave a Comment

Use lower case with MySQL. Lower name databases, tables, and columns. This keeps everything simple and you’ll never need to guess whether something is upper case or lower case or a mixed case. Also, on systems that treat “file.db” differently than “File.db”, lower case everything saves a great deal of headaches.

In every single table you have, make your first column “id”. Make it a primary key, auto-incrementing, integer. This keeps things very clean when you need to positively identify records and make changes or deletions. It also works great with the save function and object code as previously mentioned.

When referencing other tables within your system, make their column names “id_[remote_table]”.  When referencing id values from other systems outside of yours, make them “[outside_system]_id”.  This makes it easy to see whether you’re referencing something internally or externally.

August 28th, 2013

Posted In: Basics, Database

Leave a Comment

I’ve been writing PHP code for years now. I’ve written complete systems that I’ve forgotten I’ve written. I generally know what I’m doing.

But, sometimes I’m writing something and I need to make sure some kind of complicated logic will work correctly. Or I can’t remember exactly how a certain function will behave with certain inputs. Or I need to run some kind of one-off report for someone. How do I do all of those things without creating tons of files for each one?

Create a test.php file. In that file, include your common file so you have database access and all your standard classes. You can optionally include visuals or whatever else you need to perform your testing. Then go ahead and test your one-line items, or write one-time use reports, or test some concepts.

What I like to do is write my code, then put an “exit” at the end of it. I leave it on the development server I work on all the time so it’s always available. The next time I need to test some piece of code, I add my code above my previous test code and add another “exit” at the end of my current test code. All of my various tests and one-time reports are in this file and it’s really easy to grab examples from previous work or see how I did something later. It’s like a functional scratch pad.

Recently the file got so big it was taking a couple seconds to upload and download it to the server. Because I also have a /test/ directory, I duplicated my test file, named it test_archive.php, and then deleted everything except the required common includes out of my test.php file and started over.

I love having my test.php file. It lets me take complicated systems and test individual little components to verify they’re working without needing to run large complicated tests on the entire new set of code I might be writing. It also lets me do real time one-off reporting as needed without setting up and formalizing actual report files.

August 28th, 2013

Posted In: Shortcuts

Leave a Comment

Looking at previous command-structure examples, you may have noticed frequent use of the header(“Location: …”) tag. Why all the redirecting?

Using the command structure, you often could just set the $command variable to something else, and then the script would go ahead and display the next item or whatever else you need it to do.

But what happens with the user refreshes or presses the back button. If they re-post the same data again, you may be dealing with duplicate data issues, form validation issues, invalid flow concepts, etc.

Using the redirect concepts avoids all of that and the user is safe to press refresh or back or do all the things that users generally do. They won’t be re-posting any form submissions and the URLs they’re provided with will be “safe”. Safe URLs are generally shareable, won’t alter data if someone else clicks on them, and don’t show the user any information that they shouldn’t know about or would be damaging for them to know about.

Redirects keep your code and your user interface clean.

August 28th, 2013

Posted In: Controllers

Leave a Comment

Just like the posting on where to put CSS, javascript functions in a similar way.

Javascript can be written in .js files or included dynamically on the page via <script> tags or even on an item-by-item basis with things like “onclick=’doStuff()'”.

If you have certain functions or variables you need to have always available and globally accessed, put them in a shared .js file that is included on every page.  This is a great way to handle some basic Ajax calls and some other shared code that is used frequently.

If you have forms that have custom requirements before submitting, include that code right in the PHP file you’re working on as a part of the visual part of your command structure.  This will make debugging easier and you can dynamically generate that form verification based on logic that PHP knows about (such as which form elements should or should not be included based on various conditions).

Sometimes you just need to do a really simple something that is unique on a per element basis: Go ahead and add javascript right into your element as needed.  Makes it easy to debug and there’s no reason to make things more complicated than you need to.

DO NOT put all of your javascript into .js files just because you think you should.  There’s no good reason to.  Instead, look at where they fit best on their own.  Some javascript may need to be dynamically generated by PHP.  Having a static .js file is incompatible with this concept.

August 28th, 2013

Posted In: Basics

Leave a Comment

When working on the visual elements of your design, where do you put the CSS?

Should you have one global stylesheet that contains all CSS for your entire project? (Some people do this.)

Should you have a couple stylesheets that are generally always included that cover everything?

Should you just write all of your CSS inline, right in the DIV and P tags?

Should your CSS be written on a page-by-page basis and be included in style tags on the page?

Answer: Some mixture of all of the above.

Your global stylesheet should be used only to define the basic look and feel of your entire system. It should not contain anything that will be used only once. Everything in that global sheet should be used repeatedly and excessively throughout your system.

Your individualized stylesheets should be used for sub-systems that share a variety of page displays and have a unique set of attributes or visual design that build upon or enhance the global stylesheet.

Individual CSS attributes can be applied to DIV, P, SPAN, and other tags for individually unique items. Likewise, you should use the style tag and include CSS information within that style tag on a per-page basis if that page shares the same CSS on multiple copies of items within the page.

DO NOT build your system with just one global stylesheet and dump everything into it. It’s a disaster waiting to happen. Plus, every time you make any change, your clients need to do a force-refresh to get the new stylesheet. “Where’s the new style?” “Press force-refresh to get it.” “How are users supposed to know they need to do that?” “Uhm…”

DO NOT write the same style into a style tag on everything. If you find yourself copy-pasting a ton of code, something’s wrong.

Use dynamically-generated CSS when and where applicable to suit your application’s needs. Sometimes you have to write your CSS on individual object items because that’s the only way to make them do exactly what you need them to do. That’s OK.

August 28th, 2013

Posted In: Basics

Leave a Comment

You should never, under any circumstance, be writing in your code more than once.

Use a header file. Call it what you want, I like ‘header.php’ or ‘header.inc.php’ and have it handle all those things.

Your code should look something like this:

<?php

// Author
// Test URL
$page_title = "Ad Edit";
$useCKeditor = true;
include 'header.php';

$command = $_REQUEST['command'];

if($command=='something) {
...

You should also never be writing more than once. That should be in a footer file. Continuing the above example:


if($command=='something_else') {
...
}

include 'footer.php';
?>

In your header you should include your common file as well as any files necessary for view-based pages. You should also have boolean options for disabling navigation and other items that aren’t necessary when performing ajax calls so you can continue to use your header for those fun things. Your footer should also have an option to not display itself (preferably inheriting the same variable as the header) and in general shouldn’t be trying to do too much.

August 20th, 2013

Posted In: Basics

Leave a Comment

Next Page »