The important thing to keep in mind is that there are a lot of established solutions to your question. One of the most effective tools is to utilize class structure with Class Injections to share global variables. I would not do this structure justice and it took me a while to make my project based on classes. The benefits are numerous though.
With well documented classes and functions, you will be developing a robust set of tools which will help you create multiple applications with the same libraries. This allows for increased efficiency in coding
With well organized classes it will be extraordinarily easy to extend the power of PHP without killing yourself. Think about this as you might with PHP's built in classes, like mysqli
. It is incredibly useful to have classes which are built to accomplish tasks you need to use multiple tasks.
With well structured code, you will be saving yourself an incredible amount of time in debugging. If you need to make a change, you will only have to do it sparingly.
Some tips:
Use constants with a separate file, where your common files like file paths exist.
Creating a config file is a great way to limit the number of times you have to type the same value over and over again, helping to fulfill one of the most important principles of coding, Don't Repeat Yourself (DRY). That means your config file can keep some common values such as:
- Your SQL username, dbname, password.
- Global values that do not need to change. For example, if you know that
BLUE
will always have the value 1, you can define('BLUE',1);
Document your code well.
I fell into this trap multiple times, and I think most coders have come to the realization at some point in their lives that they are complicating their lives simply by failing to comment. A well structured program will have classes that have functions within them that make perfect sense. But you won't really remember what those are unless you comment each class's purpose and each function within them. A great outcome of this is that you can actually describe what your functions are doing before you code them. It makes it a lot easier to make sure you are not duplicating efforts or not creating two functions where one will do/one function where two will do.
Utilize class hierarchy.
Utilizing smart class hierarchies can help you accomplish some very sleek and powerful code. Using bad class hierarchies can help you give yourself a nightmare of dependencies. For example, many of your classes will probably be calling SQL. If you are utilizing Dependency Injection then you will need a way to inject your code. Creating an abstract class
called base
can help to make that happen.
/**
* Base classes for dependency injection.
*/
Abstract class base {
protected $db,$session,$logged_in;
/**
* Sets the database $db handler.
*
* Classes which inherit this class can use $childClass->db
* to utilize any SQL queries.
*
* @param object $db Database handler from mysqli_connect.
*/
public function set_database($db) {
$this->db = $db;
}
/**
* Session injection.
*
* If you want to use dependency injection to its fullest,
* avoid globals and use something like this or more complex
* to store your sessions too.
*
* @param array $session from the $_SESSION global.
*/
function set_session($session) {
//You can store a variable to quickly check if the user is logged in.
if(!isset($session['logged_in'])) $this->logged_in = false;
else $this->logged_in = $session['logged_in'];
$this->session = $session;
}
}
/**
* The class where I do all my function execution.
*
* Because it extends base, I have the set_database function.
*/
class myClass extends base {
/**
* Delete something.
*
* @return integer The number of rows deleted.
*/
public function del_thing() {
$result = mysqli_query($db, "SELECT id, task, parent, status, created_at FROM tasks WHERE user='{$this->session['user_id']}'");
return mysqli_num_rows($result);
}
}
To call something like this, you have to execute a few extra lines of code.
//The old way
//$myClass = new myClass;
//$myClass->del_thing();
//The new way
$database = mysqli_connect(LOCALHOST, USERNAME, PASSWD, DBNAME);
$myClass = new myClass;
$myClass->set_database($database);
$myClass->set_session($_SESSION);
$myClass->del_thing();
The benefit of this method is that although you have to write a couple extra lines of code, you are then free to write your code freely. Additionally, you don't have to repeat everything multiple times. That means if you have to migrate databases, or change usernames, or anything, you make ONE change, and it is all set throughout. This helps to ensure your code is not tightly coupled, another big no-no in well crafted code.
A great way to solve any annoyance with having to declare set_database
is to utilize Pimple, which is actually the same tool that is used in the Symfony Framework, developed as a standalone tool. It is a fairly simple tool to get up and running and now, instead of what was written above, you write, one time, in an initializing library of some sort:
$container = new Pimple;
$container['myClass'] = function($c) {
$class = new myClass;
$class->set_database($database);
$class->set_session($session);
return $class;
};
Now in the future, rather than calling $myClass = new myClass;
to create a class instance, you can instead call $myClass = $container['myClass'];
. From that point on, $myClass->del_this();
will work the same way.