Page 1 of 1

One class setting calling another's method

Posted: Mon Jul 12, 2010 8:09 pm
by jbraxx
I have a Session class with a method called message. $session->message() stores a message in $_SESSION so that I can send a message from a form processing page back to the form page if some form data is missing or incorrect (i.e. if somebody skips a required field they'll be returned to the form with a message to fill in that field).

My form processing script is in my Customer class. It checks through the form data and if it catches an error it notes it in a field_errors array. At the end, if the array is empty, it returns true. If not, it redirects the user back to the form page. At least it's supposed to, but what's happening instead is I'm getting this message from PHP:

"Notice: Undefined variable: session in /Applications/MAMP/htdocs/rip/includes/customer.php on line 63

Fatal error: Call to a member function message() on a non-object in /Applications/MAMP/htdocs/rip/includes/customer.php on line 63"

The Session class is included before the Customer class, so I don't understand why it thinks session is undefined. Any idea how I can fix this? The relevant parts of the scripts are below.

Thanks!

--------------CUSTOMER CLASS----------------

Code: Select all

<?php

class Customer {
	public $name;
	public $addr1;
	public $city;
	public $state;
	public $zip;
	public $email;
	public $email_comp;
	public $field_errors = array();
	
	public function create() {
		if(!$this->name = trim($_POST['name'])) { $this->field_errors = "Please enter your name."; }
		if(!$this->addr1 = trim($_POST['addr1'])) { $this->field_errors = "Please enter your address."; }
		if(!$this->city = trim($_POST['city'])) { $this->field_errors = "Please enter your city."; }
		if(isset($_POST['state'])) { $this->state = $_POST['state']; } // not required
		if(isset($_POST['zip'])) { $this->zip = trim($_POST['zip']); } // not required
		if(!$this->email = trim($_POST['email'])) { $this->field_errors = "Please enter your email address."; }
		if($this->email != $this->email_comp) { $this->field_errors = "The email addresses you entered did not match."; }
		if(empty($this->field_errors)) {
			return true;
		} else {
			$session->message("...");
			redirect_to('index.php?page_id=5'); // This function is defined in a separate functions file and works in other contexts
		}
	}
?>
--------------SESSION CLASS----------------

Code: Select all

<?php

class Session {
	
	public $message;
	
	public function message($msg="") {
		if(!empty($msg)) {
			$_SESSION['message'] = $msg;
		} else {
			return $this->message;
		}
	}
	
	private function check_message() {
		if(isset($_SESSION['message'])) {
			$this->message = $_SESSION['message'];
			unset($_SESSION['message']);
		} else {
			$this->message = "";
		}
	}
	
	
}
?>

Re: One class setting calling another's method

Posted: Mon Jul 12, 2010 10:28 pm
by requinix
Relevant parts? How about customer.php around line, say, 63?

Re: One class setting calling another's method

Posted: Tue Jul 13, 2010 3:08 pm
by jbraxx
I cut out parts at the top to save everyone from reading through code that isn't involved. I can post the whole thing if that's easier, but what was line 63 is now near the bottom of the customer class where it makes a reference to the Session class:

Code: Select all

else {
       $session->message("...");
       redirect_to('index.php?page_id=5');

Re: One class setting calling another's method

Posted: Tue Jul 13, 2010 3:33 pm
by AbraCadaver
That makes reference to a session object but you have not instantiated an object and it wouldn't make sense to do that there anyway. You either need to create a new session object in the main code and add it to a registry and then retrieve it in the user class, or you can use the session class statically (not sure why).

Re: One class setting calling another's method

Posted: Tue Jul 13, 2010 4:24 pm
by jbraxx
The Session class gets instantiated at the top of every page, so I don't think that's the issue. I'll post the full version of the two classes here to make things clearer:

-------------------SESSION CLASS---------------------------

Code: Select all

<?php

class Session {
	
	public $message;
	
	function __construct() {
		session_name("RIP-session");
		session_start();
		if(isset($_SESSION['start_time']) && time() - $_SESSION['start_time'] > 3600) {
			$this->message("Your current session has expired and your cart has been emptied.<br />Please add items to your cart.");
			redirect_to('index.php?');
		} 
		if(!isset($_COOKIE['RIP-session'])) {
			redirect_to("error.php");
		}
		$_SESSION['start_time'] = time();
		$this->check_message();
	}
	
	public function message($msg="") {
		if(!empty($msg)) {
			// then this is "set message"
			// make sure you understand why $this->message=$msg wouldn't work
			$_SESSION['message'] = $msg;
		} else {
			// then this is "get message"
			return $this->message;
		}
	}
	
	private function check_message() {
		// Is there a message stored in the session?
		if(isset($_SESSION['message'])) {
			// Add it as an attribute and erase the stored version
			$this->message = $_SESSION['message'];
			unset($_SESSION['message']);
		} else {
			$this->message = "";
		}
	}
	
	
}
$session = new Session();
$message = $session->message();

?>
-------------------CUSTOMER CLASS---------------------------

Code: Select all

<?php

class Customer {
	protected static $table_name = "orders";
	public $order_id = "";
	public $name = "";
	public $addr1 = "";
	public $addr2 = "";
	public $city = "";
	public $state = "";
	public $province = "";
	public $zip = "";
	public $nation = "";
	public $phone = "";
	public $email = "";
	public $email_comp = "";
	public $card = "";
	public $card_no = "";
	public $exp_mo = "";
	public $exp_yr = "";
	public $ship_name = "";
	public $ship_addr1 = "";
	public $ship_addr2 = "";
	public $ship_city = "";
	public $ship_state = "";
	public $ship_province = "";
	public $ship_zip = "";
	public $ship_nation = "";
	protected $datetime;
	public $field_errors = array();
	
	public function create() {
		$this->datetime = strftime("%Y%m%d%H%M%S", time());
		if(!$this->name = trim($_POST['name'])) { $this->field_errors = "Please enter your name."; }
		if(isset($this->name, $this->datetime)) { $this->order_id = substr($this->name, 0, 4) . "-" . $this->datetime; }
		if(!$this->addr1 = trim($_POST['addr1'])) { $this->field_errors = "Please enter your address."; }
		if(isset($_POST['addr2'])) { $this->addr2 = trim($_POST['addr2']); }
		if(!$this->city = trim($_POST['city'])) { $this->field_errors = "Please enter your city."; }
		if(isset($_POST['state'])) { $this->state = $_POST['state']; }
		if(isset($_POST['province'])) { $this->province = trim($_POST['province']); }
		if(isset($_POST['zip'])) { $this->zip = trim($_POST['zip']); }
		if(!$this->nation = $_POST['nation']) { $this->field_errors = "Please enter your country."; }
		if(isset($_POST['phone'])) { $this->phone = $_POST['phone']; }
		if(!$this->email = trim($_POST['email'])) { $this->field_errors = "Please enter your email address."; }
		if($this->email != $this->email_comp) { $this->field_errors = "The email addresses you entered did not match."; }
		if(!$this->card = $_POST['card']) { $this->field_errors = "Please enter your card type."; }
		if(!$this->card_no = $_POST['card_no']) { $this->field_errors = "Please enter your credit card number."; }
		//$this->exp_mo = $_POST['exp_mo'] { $this->field_errors = "Please enter your city."; }
		if(!$this->exp_yr = $_POST['exp_yr'] && $this->exp_mo = $_POST['exp_mo']) {
			$this->field_errors = "Please enter your card's expiration date'.";
		}
		if(isset($_POST['ship_name'])) { $this->ship_name = trim($_POST['ship_name']); }
		if(isset($_POST['ship_addr1'])) { $this->ship_addr1 = trim($_POST['ship_addr1']); }
		if(isset($_POST['ship_addr2'])) { $this->ship_addr2 = trim($_POST['ship_addr2']); }
		if(isset($_POST['ship_city'])) { $this->ship_city = trim($_POST['ship_city']); }
		if(isset($_POST['ship_state'])) { $this->ship_state = $_POST['ship_state']; }
		if(isset($_POST['ship_province'])) { $this->ship_province = trim($_POST['ship_province']); }
		if(isset($_POST['ship_zip'])) { $this->ship_zip = $_POST['ship_zip']; }
		if(isset($_POST['ship_nation'])) { $this->ship_nation = $_POST['ship_nation']; }
		if(empty($this->field_errors)) {
			return true;
		} else {
			$session->message("...");
			redirect_to('index.php?page_id=5');
		}
	}
	
}

?>

Re: One class setting calling another's method

Posted: Tue Jul 13, 2010 4:34 pm
by AbraCadaver
Right, so $session is a global var and isn't available in class or the method unless you define it global or access it as $GLOBALS['session'], which would totally negate using OOP. Look at the registry pattern. Add objects that you need application wide and then retrieve them where you need them: http://www.phppatterns.com/docs/design/the_registry

Another way, depending on how your app is designed, would be to create an application object or something that creates and stores these other objects.