The first thing to do is to sort out the class you wrote. It is not bad but you miss the proper jargon and then it is a bit messed. I think I would add some advice to keep you running.
Setter and getter function are function you can use to manipulate object private fields without exploiting them. They are useful for doing sanity check of the value you want to store in the class instance, for example.
Usually they are called get and set. You can use the automagic functions to create them but, to me, you save some typing but have to struggle with autocompletion of your ide and just a method is too generic.
You need to keep the code of the class separated from the one that loads/stores the value from the db or retrieve the user input from the web. Every chunk of code has to do just one thing (and do it at your best).
class User {
private $name;
private $birthdate;
private $age;
private $department;
private $id; // if you save in a db, you need an id
function __construct()
{
$this->id = 0;
$this->$name = '';
$this->birthdate = '';
$this->age = '';
$this->department = '';
}
function getId(): Int
{
return $this->id;
}
function setId($id) {
// check if $id contains a correct value (left as exercise)
$this->id = $id;
}
function setName(String $name)
{
if ($name === '') {
throw new \UnexpectedValueException("The user name is empty");
}
$this->name = $name;
}
function getName(): String
{
return $this->name;
}
/**
* The format of the field is YYYY/mm/dd, but you do not have to
* struggle with the format you need when you create your setter,
* keep you interface easy to use (you'll do it a lot of times),
* not to code (you need to wrote it just once).
*
* I will do just some obvious check for a valid date, just to
* show the point, you will have to complete them.
*
* The issue here is that the setter check the value before storing it
* to assure the developer that the value stored are valid ones (is not
* that simple usually)
**/
function setBirtdate(Int $day, Int $month, Int $year)
{
if ($day > 31) {
throw new \UnexpectedValueException("Invalid day of the month");
}
if ($month < 1 or $month > 12) {
throw new \UnexpectedValueException("This month does not exists");
}
if ($month == 2 ans $day > 29) {
throw new \UnexpectedValueException("February has just 28 days (29 in the leap years)");
}
/* add other checks there, how about the 31 of April, for example?) */
$this->birthDate = sprintf("%04d-%02d-%02d", $year, $month, $day);
}
/**
* You can have more than a setter, if you need to accomodate different
* use case for storing a value.
* If you live in the USA, maybe you want to stick with their common
* date format.
*
* As you see, it is a facade, I do not duplicate the code that manipulate
* the value, just stick with the canonical one, it will spare a lot of
* headache in you (near) future
**/
function setBirtdate_USA_format(Int $month, Int $day, Int $year)
{
$this->setBirthday($day, $month, $year);
}
/**
* Same with the getter, but only one does the work
* CHECK THE VALUE
* If you need a getter and a setter that get just
* your native format, and checks if it make sense,
* feel free to write it by yourself :-)
**/
function getBirthdate()
{
list($year, $month, $day) = explode("/", $this->birthdate);
return [$day, $month, $year];
}
function getBirthdate_USA_format()
{
list($day, $month, $year) = $this->getBirtdate();
return [$month, $day, $year];
}
function setAge($age)
{
if ($age < 1) {
throw new \UnexpectedValueException("No newborn allowed, please");
}
$this->age = $age;
}
function getAge()
{
return $this->age;
}
/**
* This is an interesting one, how discover if the department
* exists, or the string is not mispelled?
* There are a lot of valid ways to do this check, but it
* depends on the environment you are in, maybe there is a
* class Department, you can leverage, or a higher level one,
* which mantains a list of departments in place.
*
* We will resort to an hardcoded lists of valid deps, just to
* keep the example (not so) short and simple.
**/
function setDepartment($departmentName)
{
$knowDeps = ['Human Resource', 'Sales', 'Legal'];
if (!in_array($departmentName, $knowDeps)) {
throw new \UnexpectedValueException("The department {$departmentName} does not exists");
}
$this->department = $departmenetName;
}
function getDepartment()
{
return $this->department;
}
function save($dbc)
{
/* put the code for saving data to the db here */
}
}
This is just a first draft of such a class, with a lot of jibberish in the comments to help you to understand what is going one.
Time to think to the HTML, you will need another class, usually called View that get a User object and create a webpage. You can have several ones to choose from, based on what do you need to accomplish.
The following is a quick and dirty solution, just to show how to use our User ojects, some one filled.
Let say we have two html fragment files in a /path/to/template/
directory. Let us call them base.html.template and contactform.html.template
The base.html
file is:
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8">
<h1>{{ contentTitle }}</h1>
{{ content }}
</div>
</div>
</div>
</body>
</html>
The contactform.html
file is:
<form name="contact-form" action="insert.php" method="POST" id="contact-form">
<input name="uid" value="{{ uid }}" type="hidden">
<div class="form-group">
<label for="Name">Name</label>
<input name="Name" value="{{ userName }}" type="text" class="form-control" name="Name" placeholder="Name" required>
</div>
<div class="form-group">
<label for="Birthday">Birthday</label>
<input name="Birth" value="{{ userBday }}" type="text" class="form-control" placeholder="YYYY/MM/DD" required>
</div>
<div class="form-group">
<label for="Age">Age</label>
<input name="Age" value="{{ userAge }}˝ type="text" class="form-control" name="Age" placeholder="Your Age" required>
</div>
<div class="form-group">
<label for="Depart">Department</label>
<input name="Depart" value="{{ userDep }}" type="text" class="form-control" placeholder="Your Department" required>
</div>
<button type="submit" class="btn btn-primary" name="submit" value="Submit" id="submit_form">Submit</button>
</form>
the {{ userName }}
jibberish are placeholder we need to substitute with actual data when we will create the page to show in the browser
class UserViewContactForm {
private $template;
function __construct() {
/* We need to load a template somehow. */
$this->template = file_get_contents(`/path/to/template/contactform.html`);
}
function render(?User $user=Null) {
/* When we do not pass any user, just show the form, otherwise
* we will fill it with the data of the user we have
* to show/edit
*/
if (!$user) {
$user = new User();
}
$fields = [
"{{ uid }} => $user->getId(),
"{{ userName }}" => $user->getName(),
"{{ userBday }}" => $user->getBirthday(),
"{{ userAge }}" => $user->getAge(),
"{{ userDep }}" => $user->getDepartment()
];
// get a copy of the template, maybe we'll need it for another one
$htmlform = $this->template;
// change all the placeholder
foreach ($fields as $field => $value) {
$htmlform = str_replace($field, $value, $htmlform);
}
return $htmlform;
}
}
We will need a BaseView object to assemble the complete html page:
class HtmlPage {
private $template;
function __construct() {
/* We need to load a template somehow. */
$this->template = file_get_contents(`/path/to/template/base.html`);
}
function render($content) {
/* When we do not pass any user, just show the form, otherwise
* we will fill it with the data of the user we have
* to show/edit
*/
// get a copy of the template, maybe we will need to show another
// user in the next future, who know.
$htmlform = $this->template;
// change all the placeholder
foreach ($fields as $field => $value) {
$htmlform = str_replace($field, $value, $htmlform);
}
return $htmlform;
}
}
Now your User Class is decoupled from the html, you can change the view without changing the class that hold your precious data.
We just need a factory to create our User from the input we get from the web user. or from a database, or from wathever other source.
It is a completely new task, so we need a completely new object.
This class have the task to create an user
Class UserFactory {
private $dbc;
function setDbConnector($pdo) {
/* just injecting an object to manage the interaction with a db */
$this->dbc = $pdo;
}
function createFromHash($data) {
/* Sometime you will need to use different verbs to
* send data to the server, hance the need to
* decouple the array we take the data from.
*
* Important, we should take the time here to
* check the input for malicious input.
* Since it is an example and I'm too lazy we will
* skip this important phase of input retrieving.
*/
$requiredFields = ['uid', 'Name', 'Birth', 'Age', 'Depart'];
$actual = array_intersect($requiredFields, array_keys($data));
if (count($requiredFields) != count($actual)) {
throw new \InvalidArgumentException("Some field is missing");
}
$user = new User();
$user->setId($data['uid']);
$user->setName($data['Name']);
$user->setBirthdate($data['Birth']);
$user->setAge($data['Age']);
$user->setDepart($data['Depart']);
return $user;
}
function createFromDb($userId) {
/* If you need to retrieve data from a database,
* just retrieve them, put in a suited array hash an
* reuse the method we already implemented.
*
* It
*/
$query = "SELECT id as "uid",
username as "Name",
birthday as "Birth",
age as "Age",
department as "Depart"
FROM users
WHERE id = :userid";
$stmt = $this->dbc->prepare($query);
$stmt->bindParam(':userid', $userId, PDO::FETCH_ASSOC);
$stmt->execute();
$data = $stmt->fetch(PDO::FETCH_ASSOC);
return $this->createFromHash($data);
}
}
How to go to the database?
I think the functions you use are really hold and maybe deprecated,
just stick with the PDO Object to work with the db.
PDO use drivers to connect different database engine assuring you can use a common interface to connect to the db and perform action on the database.
Now it is time to put all together
#Include all the php files you need
// instance $pdo, a PDO object to connect to the database
try{
$factory = new UserFactory();
$user = $factory->createFromHash($_POST);
} catch (InvalidArgumentException $e) {
$user = new User(); // an empty one
}
$page = new HtmlPage();
$contactForm = new UserViewContactForm();
echo $page->render($contactForm->render($user));
And you should have a rendered page ready to get data.
There are some corners cut, and a lot of works to get a really functioning solution there, but I think this is a base you can build on.