Advice on object-oriented form

I’m looking for advice on everything and anything for the code below. This is my first time using object-oriented programming, and I wanted to start off with something small, like a login form. I’ve written the login form in a procedural version, and in an object-oriented version. The object-oriented version includes what would be 2 different files. So there are 3 code snippets below:

  1. the procedural version
  2. the controller script for the object-oriented version
  3. the class definitions for the object-oriented version

Again, I’d appreciate any and all feedback. Thanks.

Snippet #1: procedural version

<head>
<title>Procedural</title>
</head>
<body>
<?php

session_start();

if (isset($_POST['submit']) && $_POST['submit'] == "logout")
{
	unset($_SESSION['email_address']);
	unset($_SESSION['unique_id']);
	echo "<p>logout complete</p>";
}

if (isset($_SESSION['email_address']) && $_SESSION['email_address'])
{
	echo "<p>login complete, email: " . $_SESSION['email_address'] . " number: " . $_SESSION['unique_id'] . "</p>";
	echo '<form action="" method="post">
	<p><input type="submit" name="submit" id="submit" value="logout" /></p>
	</form>';
}
else
{
	if (isset($_POST['submit']) && isset($_POST['email_address']) && isset($_POST['pass']) && $_POST['submit'] == "login")
	{
		$email_address = $_POST['email_address'];
		$pass = $_POST['pass'];
		
		if ($email_address == '')
		{
			$err[] = "email address blank";
		}
		elseif (strlen($email_address) > 20)
		{
			$err[] = "email address over 20 chars";
		}
		if (stristr($email_address, ";"))
		{
			$err[] = "email has semicolons";
		}
		if ($pass == '')
		{
			$err[] = "password blank";
		}
		elseif (strlen($pass) > 20)
		{
			$err[] = "password over 20 chars";
		}
		if (stristr($pass, ";"))
		{
			$err[] = "password has semicolons";
		}
		
		if (!isset($err))
		{
			$mysql = mysqli_connect('server', 'username', 'password', 'database');
			if (!$mysql)
			{
				die(mysqli_error($mysql));
			}
			$statement = "SELECT unique_id, email_address, pass FROM table WHERE email_address = '$email_address'";
			$resultset = mysqli_query($mysql, $statement);
			if (!$resultset)
			{
				die(mysqli_error($mysql));
			}
			$data = mysqli_fetch_array($resultset);
			if (!$data)
			{
				$err[] = "unsuccessful";
			}
			elseif ($pass != $data['pass'])
			{
				$err[] = "unsuccessful";
			}
			elseif ($pass == $data['pass'])
			{
				$_SESSION['email_address'] = $data['email_address'];
				$_SESSION['unique_id'] = $data['unique_id'];
				echo "<p>login complete, email: " . $_SESSION['email_address'] . " number: " . $_SESSION['unique_id'] . "</p>";
				echo '<form action="" method="post">
				<p><input type="submit" name="submit" id="submit" value="logout" /></p>
				</form>';
				exit();
			}
		}
	}

	if (isset($err))
	{
		foreach ($err as $problem)
		{
			echo "<p>$problem</p>";
		}
	}
	
	echo '<h1>Login Form</h1>
	<form action="" method="post">
		<p>
			<label for="email_address">what\\'s your email address?</label>
			<input type="text" name="email_address" id="email_address" />
		</p>
		<p>
			<label for="pass">what\\'s your password?</label>
			<input type="pass" name="pass" id="pass" />
		</p>
		<p>
			<input type="submit" name="submit" id="submit" value="login" />
		</p>
	</form>';
}

?>

</body>

Snippet #2: object-oriented version, controller script

<head>
<title>Object-Oriented</title>
</head>
<body>
<?php

require("classes.php");

$sess = new My\\Sess();

$submit_info = new My\\Submitted($_POST);

if ($submit_info->inputs_exist(array('submit')) && $submit_info->value_match('submit', "logout"))
{
	$sess->logout_user();
}

if ($sess->is_logged())
{
	$sess->login_info();

	$form = new My\\Form("");
	$form->new_element('submit', 'submit', 'submit', 'Log Out', '');
	$form->echo_back();
}
else
{
	if ($submit_info->inputs_exist(array('submit', 'email_address', 'pass')) && $submit_info->value_match('submit', "Log In"))
	{
		$err = $submit_info->error_display();
		if (!$err)
		{
			$query = new My\\Select_Query($submit_info);
			$unique_id = $query->authenticate();
			if (!$unique_id)
			{
				$err = $query->error_display();
			}
			else
			{
				$sess->log_in($submit_info->value_return('email_address'), $unique_id);
				$sess->login_info();
				
				$form = new My\\Form("");
				$form->new_element('submit', 'submit', 'submit', 'Log Out', '');
				$form->echo_back();
				exit();
			}
		}
	}
	
	if (isset($err) && $err)
	{
		echo $err;
	}

	$form = new My\\Form("Login");
	$form->new_element('email_address', 'email_address', 'text', '', 'what\\'s your email address?');
	$form->new_element('pass', 'pass', 'pass', '', 'what\\'s your password?');
	$form->new_element('submit', 'submit', 'submit', 'login', '');
	$form->echo_back();
}

?>

</body>

Snippet #3: object-oriented version, class definitions

<?php

namespace My;

class Sess
{
	public function __construct()
	{
		session_start();
	}

	public function logout_user()
	{
		unset($_SESSION['email_address']);
		unset($_SESSION['unique_id']);
		echo "<p>logout complete</p>";
	}

	public function log_in($email_address, $unique_id)
	{
		$_SESSION['email_address'] = $email_address;
		$_SESSION['unique_id'] = $unique_id;
	}
	
	public function is_logged()
	{
		if (isset($_SESSION['email_address']) && isset($_SESSION['unique_id']))
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	
	public function login_info()
	{
		echo "<p>login complete, email: " . $_SESSION['email_address'] . " number: " . $_SESSION['unique_id'] . "</p>";
	}
}

Class Form
{
	private $display_text = array();
	
	public function __construct($title)
	{
		if ($title)
		{
			$this->display_text[] = "<h1>$title Form</h1>";
		}
		$this->display_text[] = '<form action="" method="post">';
	}
	
	public function new_element($element_id, $element_name, $element_type, $element_value, $element_label)
	{
		$this->display_text[] = '<p>' .
			'<label for="' . $element_id . '">' . $element_label . '</label>' .
			'<input type="' . $element_type . '" name="' . $element_name . '" id="' . $element_id . '" value="' . $element_value . '" />
		</p>';
	}
	
	public function echo_back()
	{
		$this->display_text[] = '</form>';
		echo implode("", $this->display_text);
	}
}

Class Submitted
{
	private $all_inputs;
	
	public function __construct($submission)
	{
		foreach ($submission as $index => $info)
		{
			switch ($index)
			{
				case "email_address":
					$this->all_inputs[$index] = new Post_Email_Address($info);
					break;
				case "pass":
					$this->all_inputs[$index] = new Post_Pass($info);
					break;
				case "submit":
					$this->all_inputs[$index] = new Post_Submit($info);
					break;
			}
		}
	}
	
	public function inputs_exist($inputs)
	{
		if (!$this->all_inputs)
		{
			return false;
		}
		else
		{
			foreach($inputs as $field)
			{
				if (!array_key_exists($field, $this->all_inputs))
				{
					return false;
				}
			}
		}
		return true;
	}
	
	public function value_match($index, $test)
	{
		if ($this->all_inputs[$index]->value_match($test))
		{
			return true;
		}
		return false;
	}
	
	public function error_display()
	{
		$err = "";
		foreach ($this->all_inputs as $input)
		{
			if (get_class($input) != "My\\Post_Submit")
			{
				$err .= $input->error_display();
			}
		}
		return $err;
	}
	
	public function value_return($index)
	{
		if ($index == 'email_address')
		{
			return $this->all_inputs[$index]->value_return();
		}
	}	
}

Class Post_Input
{
	protected $user_data;
	protected $minimum_chars;
	protected $maximum_chars;
	
	public function __construct($info)
	{
		$this->user_data = $info;
	}
	
	public function value_match($test)
	{
		if ($this->user_data == $test)
		{
			return true;
		}
		return false;
	}
}

Class Post_Email_Address extends Post_Input
{
	private $err;
	
	public function __construct($info)
	{
		parent::__construct($info);
		$this->minimum_chars = 1;
		$this->maximum_chars = 20;
		if (strlen($this->user_data) < $this->minimum_chars)
		{
			$this->err[] = "email address blank";
		}
		elseif (strlen($this->user_data) > $this->maximum_chars)
		{
			$this->err[] = "email address over 20 chars";
		}
		if (stristr($this->user_data, ';'))
		{
			$this->err[] = "email has semicolons";
		}
	}
	
	public function error_display()
	{
		if ($this->err)
		{
			return "<p>" . implode("<p></p>", $this->err) . "</p>";
		}
		else
		{
			return "";
		}
	}
	
	public function value_return()
	{
		return $this->user_data;
	}
}

Class Post_Pass extends Post_Input
{
	private $err;
	
	public function __construct($info)
	{
		parent::__construct($info);
		$this->minimum_chars = 1;
		$this->maximum_chars = 20;
		if (strlen($this->user_data) < $this->minimum_chars)
		{
			$this->err[] = "password blank";
		}
		elseif (strlen($this->user_data) > $this->maximum_chars)
		{
			$this->err[] = "password over 20 chars";
		}
		if (stristr($this->user_data, ';'))
		{
			$this->err[] = "password has semicolons";
		}
	}
		
	public function error_display()
	{
		if ($this->err)
		{
			return "<p>" . implode("<p></p>", $this->err) . "</p>";
		}
		else
		{
			return "";
		}
	}
}
	
Class Post_Submit extends Post_Input
{
	public function __construct($info)
	{
		parent::__construct($info);
	}
}

Class Mysql_Connection
{
	protected $connect;
	protected $statement;
	
	public function __construct()
	{
		$this->connect = new \\mysqli('server', 'username', 'password', 'database');
		if ($this->connect->connect_error)
		{
			die($this->connect->error);
		}
	}
}

Class Select_Query extends Mysql_Connection
{
	private $submit_info;
	private $resultset;
	private $data;
	private $err = array();
	
	public function __construct(&$submit_info)
	{
		parent::__construct();
		$this->submit_info =& $submit_info;
		$this->statement = "SELECT unique_id, pass FROM table WHERE email_address = '" . $this->submit_info->value_return('email_address') . "'";
	}

	public function authenticate()
	{
		$this->resultset = $this->connect->query($this->statement);
		if (!$this->resultset)
		{
			die($this->connect->error);
		}

		if (!$this->data = $this->resultset->fetch_array())
		{
			$this->err[] = "unsuccessful";
		}
		elseif (!$this->submit_info->value_match('pass', $this->data['pass']))
		{
			$this->err[] = "unsuccessful";
		}
		elseif ($this->submit_info->value_match('pass', $this->data['pass']))
		{
			return $this->data['unique_id'];
		}

		return false;
	}
	
	public function error_display()
	{
		return "<p>" . implode("<p></p>", $this->err) . "</p>";
	}
}


?>

Just wanted to say again that I’d really appreciate any sort of advice on this, whether it’s about the overall structure, class definitions, or anything else. Thanks.

I wrote some long examples in other threads that might help you. An OO login script, and an [url=http://www.sitepoint.com/forums/showthread.php?835015-Use-private-function-from-one-file-in-a-public-function-in-another]OO MVC implementation.

Thanks a lot. Those look very helpful and detailed. I’ll spend some time going through them in-depth.