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

Sometimes you need to modify a system to have it work a certain way for a certain customer. Maybe every time this particular customer buys one widget we actually credit their account with two widgets.

So how do you go about modifying your code to make that happen? You could just write in the code:

if($customer=="greedy_guys") {
	$numWidgets = $numWidgets * 2;
}

Which works fine. But then what if your boss wants an email notification to go out as well when this happens? Then your code becomes:

if($customer=="greedy_guys") {
	$numWidgets = $numWidgets * 2;
	$to = 'myboss@mycompany.com';
	$from = 'thesystem@mycompany.com';
	$subject = 'Greedy Guys got more widgets';
	$body = 'Hello Boss,';
	$body .= '<br><br>Just letting you know that Greedy Guys';
	$body .= 'Got '.$numWidgets.' for the price of '.$numWidgets/2;
	$body .= '<br><br>--<br>The System';
	email_send($to,$from,$subject,$body);
}

So then the boss works out a new deal and now they’re only going to get 2 widgets for the price of 1 if there’s some other situation that occurs, otherwise they get some other complicated formula. So you code becomes:

if($customer=="greedy_guys") {
	$originalNumWidgets = $numWidgets;
	if($thisScenario===true) {
		$numWidgets = $numWidgets * 2;
	} else {
		$numWidgets = $numWidets + round((dateFormat('now','j') % 6),0);
	}
	$to = 'myboss@mycompany.com';
	$from = 'thesystem@mycompany.com';
	$subject = 'Greedy Guys got more widgets';
	$body = 'Hello Boss,';
	$body .= '<br><br>Just letting you know that Greedy Guys';
	$body .= 'Got '.$numWidgets.' for the price of '.$originalNumWidgets;
	$body .= '<br><br>--<br>The System';
	email_send($to,$from,$subject,$body);
}

Now let’s say you’re making all of these changes and then some other changes need to happen on this same page that are critical that have nothing to do with this client but the changes you’ve made for this client haven’t been fully approved yet. What do you do?

Use included files and subcommands.

In our original file, let’s call it “checkout.php”, your code becomes:

if($customer=="greedy_guys") {
	$subcommand = "process_checkout";
	include 'customizations/greedy_guys/greedy.inc.php';
}

In customizations/greedy_guys/greedy.inc.php you have:

if($subcommand=='process_checkout') {
	if($customer=="greedy_guys") {
		$originalNumWidgets = $numWidgets;
		if($thisScenario===true) {
			$numWidgets = $numWidgets * 2;
		} else {
			$numWidgets = $numWidets + round((dateFormat('now','j') % 6),0);
		}
		$to = 'myboss@mycompany.com';
		$from = 'thesystem@mycompany.com';
		$subject = 'Greedy Guys got more widgets';
		$body = 'Hello Boss,';
		$body .= '<br><br>Just letting you know that Greedy Guys';
		$body .= 'Got '.$numWidgets.' for the price of '.$originalNumWidgets;
		$body .= '<br><br>--<br>The System';
		email_send($to,$from,$subject,$body);
	}
}

Now you can go nuts with the customizations for that client and not have it muck up your original checkout page so much.

Important takeaways here: Use included subcommands like this if you need to modify existing page variables on the original system inline and/or have customizations that lend themselves well to this style of coding.

August 20th, 2013

Posted In: Controllers, Syntax

Leave a Comment

If you’re writing a complex piece of logic, make it easier for yourself later. I’m going to provide two code examples below and I’d like you to choose which one you’re rather work with.

Hint: There’s generally no need to nest if statements more than 1 or 2 levels deep. Use additional variables to guide your code through how to evaluate itself.

Version 1:

function isCandidateProfileVisible($params=array()) {
	
	if($this->profileVisibleData['showLinkToApplicant']===NULL) {
			
		
		$isDTstaff = $_SESSION['client']['isDTstaff'];
		$id_company = $_SESSION['client']['id_company'];
		
		$id_user = $_SESSION['client']['id_contact'];
		if($id_user=='') {
			$id_user = $_SESSION['session_id_user'];
		}
		
		if($params['isDTstaff']===true) {
			$isDTstaff = true;
		}
		
		$showLinkToApplicant = false;
		$howAccessGranted = NULL;
		
		if($isDTstaff) {
			$showLinkToApplicant = true;
			$howAccessGranted = "DT Staff";
		} else {
			if(strtolower($this->getOwner())=="client") {
				$showLinkToApplicant = true;
				$howAccessGranted = "owner=client";
			} else {
				if($this->getActivityStage()>=2) {
					$showLinkToApplicant = true;
					$howAccessGranted = "getActivityStage";
				} else {
					$currentEmployee = strtolower($this->getCurrentEmployee());
					if($currentEmployee=='yes' || $currentEmployee=='alumni') {
						$showLinkToApplicant = true;
						$howAccessGranted = "current/alumni employee";
					} else {
						$accessObj = $params['accessObject'];
						if(is_object($accessObj) && $accessObj->id!='') {
							$viewApps = $accessObj->getViewApps();
						} else {
							$query = "SELECT viewApps FROM access 
										WHERE id_company='".$id_company."' 
											AND id_contact='".$_SESSION['client']['id_contact']."'";
							$viewApps = getMySQLValue($query,true);
						}
						if(strtolower($viewApps)=="all") {
							$showLinkToApplicant = true;
							$howAccessGranted = "viewApps=all";
						} else {
							$jobObj = $params['jobObj'];
							$jobviewapps = false;
							
							$id_job = $params['id_job'];
							if(!is_object($jobObj) && $id_job!='') {
								$jobObj = new job($id_job);
							}
							
							if($id_job=='' && is_object($jobObj)) {
								$id_job = $jobObj->id;
							}
							
					
							$jobAccessObj = $params['jobAccessObj'];
							if(is_object($jobAccessObj) && $jobAccessObj->id!='') {
								$jobviewapps = $jobAccessObj->getViewApps();
							} else if($id_job!='') {
								$id_user = $_SESSION['session_id_user'];
								$query = "SELECT viewapps FROM jobaccess 
											WHERE id_job='".$id_job."' 
											AND id_contact='".$id_user."'";
								$jobviewapps = getMySQLValue($query,true);
							}
							
							if($jobviewapps!==false && strtolower($jobviewapps)=="all") {
								$showLinkToApplicant = true;
								$howAccessGranted = "jobviewapps=all";
							} else {
								$id_most_recent_job = $this->getMostRecentIDjob();
								if($id_most_recent_job>0) {
									$query = "SELECT Status_ActiveOrPending FROM jobs 
												WHERE id='".$id_most_recent_job."'";
									$Status_ActiveOrPending = getMySQLValue($query,true);
									if($Status_ActiveOrPending!='Yes') {
										$showLinkToApplicant = true;
										$howAccessGranted = "most recent job (".$id_most_recent_job.") ";
										$howAccessGranted .= "is not active or pending";
									} else {
										$query = "SELECT viewapps FROM jobaccess 
													WHERE id_job='".$id_most_recent_job."' 
														AND id_contact='".$id_user."'";
										$jobviewapps = getMySQLValue($query,true);
										if(strtolower($jobviewapps)=="all") {
											$showLinkToApplicant = true;
											$howAccessGranted = "jobviewapps=all";
										} else {
											if(is_object($jobObj) && $jobObj->id>0) {
				
												if(	strtolower($jobObj->getFlagAppAccessClient())=="view" 
													|| strtolower($jobObj->getFlagAppAccessClient())=="edit") {
													
													$showLinkToApplicant = true;
													$howAccessGranted = "getFlagAppAccessClient=";
													$howAccessGranted .= $jobObj->getFlagAppAccessClient()." on ".$jobObj->id;
												} else {
													$query = "SELECT r.id
																FROM responses AS r 
																LEFT JOIN jobs AS j ON j.id=r.id_job 
																WHERE r.id_applicant='".$this->id."'
																	AND 
																		(
																			j.flag_masterlist='client'
																			OR
																			j.title='Future Opportunities'
																		)
																LIMIT 1";
													$id_self_service_response = getMySQLValue($query,true);
													if($id_self_service_response) {
														$showLinkToApplicant = true;
														$howAccessGranted = "self service job found via response record: ";
														$howAccessGranted .= $id_self_service_response;
													} else {
														if($this->getOwner()=='') {
															$showLinkToApplicant = true;
															$howAccessGranted = "owner=NULL";
														} else {
															$query = "SELECT f.id
																		FROM flags AS f 
																		LEFT JOIN jobs AS j ON j.id=f.id_job 
																		WHERE f.id_applicant='".$this->id."'
																			AND 
																				(
																					j.flag_masterlist='client'
																					OR
																					j.title='Future Opportunities'
																				)
																		LIMIT 1";
															$id_self_service_response = getMySQLValue($query,true);
															if($id_self_service_response) {
																$showLinkToApplicant = true;
																$howAccessGranted = "self service job found via flag record: ";
																$howAccessGranted .= $id_self_service_response;
															} else {
																if($this->getIDreferrer()=='15') {
																	$showLinkToApplicant = true;
																	$howAccessGranted = "Candidate referrer is 'Our Corporate Website'";
																} else {
																	$query = "SELECT r.id
																				FROM responses AS r 
																				WHERE r.id_applicant='".$this->id."'
																					AND id_referrer='15'
																				LIMIT 1";
																	$id_website_application = getMySQLValue($query,true);
																	if($id_website_application) {
																		$showLinkToApplicant = true;
																		$howAccessGranted = "'our corporate website' referrer via response record: ";
																		$howAccessGranted .= $id_website_application;
																	} else {
																		$query = "SELECT id FROM activity 
																					WHERE id_applicant='".$this->id."'
																						AND activity_type='access'";
																		$id_access_activity = getMySQLValue($query,true);
																		if($id_access_activity) {
																			$showLinkToApplicant = true;
																			$howAccessGranted = "access activity record found: ".$id_access_activity;
																		} else {
																			$howAccessGranted = "Not Granted";
																		}
																	}
																}
															}
														}
													}
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}

		$this->profileVisibleData['showLinkToApplicant'] = $showLinkToApplicant;
		$this->profileVisibleData['howAccessGranted'] = $howAccessGranted;
	
	}
	
	
	if($params['returnKind']=="" || $params['returnKind']=="boolean") {
		return $this->profileVisibleData['showLinkToApplicant'];
	} else if($params['returnKind']=="howAccessGranted" || $params['returnKind']=="debug") {
		return $this->profileVisibleData['howAccessGranted'];
	}
}

Version 2:

function isCandidateProfileVisible($params=array()) {
	
	if($this->profileVisibleData['showLinkToApplicant']===NULL) {
			
		
		$isDTstaff = $_SESSION['client']['isDTstaff'];
		$id_company = $_SESSION['client']['id_company'];
		
		$id_user = $_SESSION['client']['id_contact'];
		if($id_user=='') {
			$id_user = $_SESSION['session_id_user'];
		}
		
		if($params['isDTstaff']===true) {
			$isDTstaff = true;
		}
		
		$showLinkToApplicant = false;
		$howAccessGranted = NULL;
		
		$useInternalDTrules = false;
		if($isDTstaff && $this->getIDclient()=='9786') {
			$useInternalDTrules = true;
		}
		

		if(!$showLinkToApplicant && $isDTstaff) {
			$showLinkToApplicant = true;
			$howAccessGranted = "DT Staff";
		}

		if(!$showLinkToApplicant && strtolower($this->getOwner())=="client") {
			$showLinkToApplicant = true;
			$howAccessGranted = "owner=client";
		}
		
		if(!$showLinkToApplicant && $this->getActivityStage()>=2) {
			$showLinkToApplicant = true;
			$howAccessGranted = "getActivityStage";
		}
		
		if(!$showLinkToApplicant) {
			$currentEmployee = strtolower($this->getCurrentEmployee());
			if($currentEmployee=='yes' || $currentEmployee=='alumni') {
				$showLinkToApplicant = true;
				$howAccessGranted = "current/alumni employee";
			}
		}

		if(!$showLinkToApplicant) {
			$accessObj = $params['accessObject'];
			if(is_object($accessObj) && $accessObj->id!='') {
				$viewApps = $accessObj->getViewApps();
			} else {
				$query = "SELECT viewApps FROM access 
							WHERE id_company='".$id_company."' 
								AND id_contact='".$_SESSION['client']['id_contact']."'";
				$viewApps = getMySQLValue($query,true);
			}

		}

		if(!$showLinkToApplicant && strtolower($viewApps)=="all") {
			$showLinkToApplicant = true;
			$howAccessGranted = "viewApps=all";
		}
		
		// special rules for DT persons viewing DT candidates (internal jobs, etc.)
		if($useInternalDTrules) {
			// the above rules don't apply to this situation so we should override any previous data
			$showLinkToApplicant = false;
			$howAccessGranted = NULL;
		}
		

		if(!$showLinkToApplicant) {
			$jobObj = $params['jobObj'];
			$jobviewapps = false;
			
			$id_job = $params['id_job'];
			if(!is_object($jobObj) && $id_job!='') {
				$jobObj = new job($id_job);
			}
			
			if($id_job=='' && is_object($jobObj)) {
				$id_job = $jobObj->id;
			}
			
	
			$jobAccessObj = $params['jobAccessObj'];
			if(is_object($jobAccessObj) && $jobAccessObj->id!='') {
				$jobviewapps = $jobAccessObj->getViewApps();
			} else if($id_job!='') {
				$id_user = $_SESSION['session_id_user'];
				$query = "SELECT viewapps FROM jobaccess 
							WHERE id_job='".$id_job."' 
							AND id_contact='".$id_user."'";
				$jobviewapps = getMySQLValue($query,true);
			}
				
	
			if($jobviewapps!==false && !$showLinkToApplicant && strtolower($jobviewapps)=="all") {
				$showLinkToApplicant = true;
				$howAccessGranted = "jobviewapps=all";
			}
			
			
			
			if(!$showLinkToApplicant) {
				$id_most_recent_job = $this->getMostRecentIDjob();
				if($id_most_recent_job>0) {
					$query = "SELECT Status_ActiveOrPending FROM jobs 
								WHERE id='".$id_most_recent_job."'";
					$Status_ActiveOrPending = getMySQLValue($query,true);
					if($Status_ActiveOrPending!='Yes') {
						$showLinkToApplicant = true;
						$howAccessGranted = "most recent job (".$id_most_recent_job.") ";
						$howAccessGranted .= "is not active or pending";
					} else {
						$query = "SELECT viewapps FROM jobaccess 
									WHERE id_job='".$id_most_recent_job."' 
										AND id_contact='".$id_user."'";
						$jobviewapps = getMySQLValue($query,true);
						if(strtolower($jobviewapps)=="all") {
							$showLinkToApplicant = true;
							$howAccessGranted = "jobviewapps=all";
						}
					}
				}
			}
			
			
			if(!$showLinkToApplicant && is_object($jobObj) && $jobObj->id>0) {
				
				if(	strtolower($jobObj->getFlagAppAccessClient())=="view" 
					|| strtolower($jobObj->getFlagAppAccessClient())=="edit") {
					
					$showLinkToApplicant = true;
					$howAccessGranted = "getFlagAppAccessClient=";
					$howAccessGranted .= $jobObj->getFlagAppAccessClient()." on ".$jobObj->id;
				}
			}
		}
		
		
		if(!$showLinkToApplicant) {
			// check to see if the app has applied to any self-service jobs
			$query = "SELECT r.id
						FROM responses AS r 
						LEFT JOIN jobs AS j ON j.id=r.id_job 
						WHERE r.id_applicant='".$this->id."'
							AND 
								(
									j.flag_masterlist='client'
									OR
									j.title='Future Opportunities'
								)
						LIMIT 1";
			$id_self_service_response = getMySQLValue($query,true);
			if($id_self_service_response) {
				$showLinkToApplicant = true;
				$howAccessGranted = "self service job found via response record: ";
				$howAccessGranted .= $id_self_service_response;
				if($this->getIDclient()=='104093') {
					$subcommand="correct_hm_access";
					require config_include_path_constant.'client/reports/104093/dr.inc.php';
				}
			}
		}
		
		if(!$showLinkToApplicant && $this->getOwner()=='') {
			$showLinkToApplicant = true;
			$howAccessGranted = "owner=NULL";
		}
		
		if(!$showLinkToApplicant) {
			// check to see if the app has been attached to any self-service jobs
			$query = "SELECT f.id
						FROM flags AS f 
						LEFT JOIN jobs AS j ON j.id=f.id_job 
						WHERE f.id_applicant='".$this->id."'
							AND 
								(
									j.flag_masterlist='client'
									OR
									j.title='Future Opportunities'
								)
						LIMIT 1";
			$id_self_service_response = getMySQLValue($query,true);
			if($id_self_service_response) {
				$showLinkToApplicant = true;
				$howAccessGranted = "self service job found via flag record: ";
				$howAccessGranted .= $id_self_service_response;
				if($this->getIDclient()=='104093') {
					$subcommand="correct_hm_access";
					require config_include_path_constant.'client/reports/104093/dr.inc.php';
				}
			}
		}
		
		/*
			2013-06-03: Jay says that all candidates that come from the "Our Corporate Website" 
			should be visible by the client.
		*/
		if(!$showLinkToApplicant) {
			if($this->getIDreferrer()=='15') {
				$showLinkToApplicant = true;
				$howAccessGranted = "Candidate referrer is 'Our Corporate Website'";
			}
		}
		
		if(!$showLinkToApplicant) {
			// check to see if the app has applied to any self-service jobs
			$query = "SELECT r.id
						FROM responses AS r 
						WHERE r.id_applicant='".$this->id."'
							AND id_referrer='15'
						LIMIT 1";
			$id_website_application = getMySQLValue($query,true);
			if($id_website_application) {
				$showLinkToApplicant = true;
				$howAccessGranted = "'our corporate website' referrer via response record: ";
				$howAccessGranted .= $id_website_application;
			}
		}
		
		if(!$showLinkToApplicant) {
			// check to see if any activity "access" records have been created
			// this may need to be modified later to check for job-specific
			// restrictions and/or contact-specific restrictions
			$query = "SELECT id FROM activity 
						WHERE id_applicant='".$this->id."'
							AND activity_type='access'";
			$id_access_activity = getMySQLValue($query,true);
			if($id_access_activity) {
				$showLinkToApplicant = true;
				$howAccessGranted = "access activity record found: ".$id_access_activity;
			}
			
		}
		
			
		
		if($howAccessGranted=='') {
			$howAccessGranted = "Not Granted";
		}
		
		$this->profileVisibleData['showLinkToApplicant'] = $showLinkToApplicant;
		$this->profileVisibleData['howAccessGranted'] = $howAccessGranted;
	
	}
	
	
	if($params['returnKind']=="" || $params['returnKind']=="boolean") {
		return $this->profileVisibleData['showLinkToApplicant'];
	} else if($params['returnKind']=="howAccessGranted" || $params['returnKind']=="debug") {
		return $this->profileVisibleData['howAccessGranted'];
	}
}

August 12th, 2013

Posted In: Controllers, Syntax

Leave a Comment

I believe in having controllers that are straightforward and relatively simple. Decoding the logic of your controller should be an oxymoron. There’s very few times that a controller needs to have very sophisticated logic.

In the example below I’m going to show how based on user inputs the system will decide what steps need to be taken by the user and how it all works very cleanly within the command structure. This is a rather simple example but hopefully you can see how it could be modified for far more complex situations. I’m also keeping the forms and structures overly-simple for demonstration purposes. I’m also assuming that I’m using a pretty simple object.

You will see in this and other examples that I often mix my views and controllers in one file. This is not an issue so long as you’re using the command structure so it’s obvious which bits and pieces are views and which are controllers. When you loose that distinction is when you really get in trouble with messy code.

<?php

include 'header.php';

$command = $_REQUEST['command'];
if($command=='') {
	$command = 'pre-eval';
}

$myObj = new my_object($_REQUEST['id_my_object']);

// This is a very basic controller that figures out where to start (or end)
if($command=='pre-eval') {
	if($myObj->getFeeling()!='' && $myObj->getProgramming()!='') {
		header("Location: ".$_SERVER['PHP_SELF']."?command=thank&id_my_object=".$myObj->id);
		exit;
	} else {
		header("Location: ".$_SERVER['PHP_SELF']."?command=step1&id_my_object=".$myObj->id);
		exit;
	}
}
		
// This is essentially a "view" that presents a form
if($command=='step1') {
	?>
		<form action="<?=$_SERVER['PHP_SELF']?>" method='post'>
			<input type='hidden' name='command' value='step1_save'>
			<input type='hidden' name='id_my_object' value="<?=$myObj->id?>">
			How are you feeling today?
			<select name='feeling'>
				<option value="">Please Select</option>
				<option value="Great">Great</option>
				<option value="OK">OK</option>
				<option value="Awful">Awful</option>
				<option value="Unsure">I dunno</option>
			</select>
			<br>
			<label>
				<input type='checkbox' name='doStep2' value='true'> I want to answer more questions
			</label>
			<br>
			<input type='submit' value='Continue'>
		</form>
	<?
}


if($command=='step1_save') {
	$myObj->setFeeling($_REQUEST['feeling']);
	$myObj->Save();
	if($_REQUEST['doStep2']=='true') {
		header("Location: ".$_SERVER['PHP_SELF']."?command=step2&id_my_object=".$myObj->id);
		exit;
	} else {
		header("Location: ".$_SERVER['PHP_SELF']."?command=thank&id_my_object=".$myObj->id);
		exit;
	}
}

if($command=='step2') {
	?>
		<form action="<?=$_SERVER['PHP_SELF']?>" method='post'>
			<input type='hidden' name='command' value='step2_save'>
			<input type='hidden' name='id_my_object' value="<?=$myObj->id?>">
			Do you like programming?
			<select name='like_programming'>
				<option value="">Please Select</option>
				<option value="Yes">Yes</option>
				<option value="No">No</option>
				<option value="Unsure">I dunno</option>
			</select>
			<br>
			<input type='submit' value='Continue'>
		</form>
	<?
}

if($command=='step2_save') {
	$myObj->setProgramming($_REQUEST['like_programming']);
	$myObj->Save();
	header("Location: ".$_SERVER['PHP_SELF']."?command=thank&id_my_object=".$myObj->id);
	exit;
}

if($command=='thank') {
	?>
		Thank you for completing the questions.  You said:<br>
		Feeling: <?=$myObj->getFeeling()?>
		<? if($myObj->getProgramming()!='') {
			<br>
			Programming: <?=$myObj->getProgramming()?>
		}
		
	<?
}

?>

August 12th, 2013

Posted In: Controllers

Leave a Comment