The best practices for creating a toolbar


#1

Hello! I built(for learning purposes) a very small app that helps me schedule my day by creating/deleting/editing tasks. For now i have a toolbar with two buttons: edit, delete. I’m processing this buttons trough a very simple php script in which i’m using a switch(when i click edit for task 1 it goes to toolbar.php?action=edit&id=1):

switch($action){
     case 'edit':
         //edit that task
     break;
     case 'delete':
         //delete that task
     break;
}

However i don’t think that this is a very good practice and i’m trying to find a better solution. Can somebody please help me? X_X


#2

Well, you can tackle this in many ways. You can create separate files for each individual task, you can create a single file that uses the URL to determine which task to load kind of like what you are doing there, or you can do what you are doing. None of them are wrong.

I would just suggest maybe separate the PHP heavy codes from your HTML codes. This makes it easier to read and for you to maintain.


#3

Hey @spaceshiptrooper, but which one is used and/or accepted today? X_X

I mean i’m trying to understand, for example somebody told me that my approach is outdated and i should take a look at laravel and see how they do it but i don’t get it X_X


#4

Ah. Laravel is a framework which was written in an architecture pattern called MVC. MVC is actually something that’s a little bit difficult for most beginners to understand. Now, I won’t assume your knowledge of PHP but there are other ways of almost achieving something like MVC.


#5

@spaceshiptrooper, MVC is the next lesson for me :smiley: but lets say that i understand MVC(i mean its definition) - what would be a proper way to create a toolbar in an app that’s written in an MVC way?


#6

MVC requires an extensive knowledge in OOP. If you understand OOP in PHP then you can easily write one up. But if you only know procedural, then it’s going to be a little bit harder to write. I have written a thread that does something similar to MVC, but in a procedural way. You can find it here.


#7

Hmm, i will ready it but i do understand OOP(i mean of course i’m not extremely advanced but i do get it. So in other words you say that i should create(in this case) a task as an object and then use that blueprint to edit it therefore i won’t need to write a separate toolbar script?

And hey, thank you sooo much for taking time to answer to my dummy questions! :smiley: <3


#8

Yes. The toolbar file should contain different methods of tasks. I’ll see if I can write you a guide on how I would do it in 9 hours. And no problem. I’m happy to help anyone on these forums who are stuck. :slight_smile:


#9

:open_mouth: if you can write a guide for me i will be extremely happy :D:D:D:D:D:D!!!


#10

That’s only if no one replies to your topic. All are welcomed to provide their input.


#11

Sorry. Been busy. So what I would do is look at the toolbar file as a bootstrap file for our final product. The main purpose of the toolbar file is to pretty much instantiate the necessary files to do the task. Each task such as Edit, Delete, Update, etc are all controllers. These controllers will then have 1 method called id. In the id method, we take in 1 argument that’s strictly an integer by type hinting it. We do not want strings being passed as the id will only consist of integers.

So to do so, we must first configure our .htaccess file to take in 2 parameters of the URL. I typically call these “segments” once they are combined with forward slashes. So to do so, we’ll have to write something like so.

RewriteEngine On
RewriteBase /

Options -Indexes

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^toolbar/(.+)/(.+)$ /toolbar.php?action=$1&id=$2 [QSA,L]
RewriteRule ^toolbar/(.+)$ /toolbar.php?action=$1 [QSA,L]

The file toolbar.php will take in 2 parameters, action and id. action will later become our controllers and id will tell the controllers which ID to use. The second rewrite rule is there for fool-proof in case someone types in /edit/ instead of /edit/1. This should give you a clear picture of how we want the URL to look. So this is where the whole “segment” part comes in. I see /edit/1 as 2 segments. edit is the first segment and 1 is the 2nd segment.

Next, we will construct our toolbar.php file. In order for us to do that, we must first check to make sure that both action and id exists within the URL. If they both don’t, then use a 404 error page. Something like the bellow.

if(isset($_GET['action']) AND isset($_GET['id'])) {

	// Both action and id exists within the URL, let's do something with them.

} else {

	// Error page here.

}

Ok. So the first few steps are kind of easy. All we really do now is assign them with variables. We will give $_GET['action'] the variable of $action and $_GET['id'] the variable of $id. This should be relatively simple. Something like the below.

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = $_GET['id'];

} else {

	// Error page here.

}

Now, we are going to type cast the id because since we are going to use type hinting, we have to actually force the id to be an integer. If we don’t, the actual data type of id is actually a string no matter if we have only numbers in that variable. Next, we’ll also have to declare that we want to use strict typing and that actually has to go first before anything. Apparently even before namespaces. So something like the below should suffice.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];

} else {

	// Error page here.

}

So now that we have our basic template done, we have to dig in further and actually do some dynamic calls. This is where it gets a little bit tricky if you don’t know what you’re doing. We’ll put all of our controllers in a folder called toolbar. We’ll also make sure that the files actually exists so we’ll use file_exists and throw that into an if statement. So something like so.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];

	if(file_exists('toolbar/' . $action . '.php')) {

		// We are good now.

	} else {

		// Error page here again.

	}

} else {

	// Error page here.

}

Next, we’ll then include the file using the require_once function. Again, if you want to know why we aren’t using the include function, you can just go look at the topic I linked before and read through it.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];

	if(file_exists('toolbar/' . $action . '.php')) {

		// We are good now.
		require_once 'toolbar/' . $action . '.php';

	} else {

		// Error page here again.

	}

} else {

	// Error page here.

}

This looks a bit promising, but this isn’t everything. People just stop at this point and just start writing their task files. I honestly think this is a bad idea. I am not a fan of mushing everything up into 1 single file. This is a terrible idea that will backfire hard. So we go further using OO. Next, we’ll dynamically call a class, call the method, and pass in a variable within the method. This should be sufficient enough to do our tasks. So to dynamically call the class, we’ll have to know what we are going to be naming our classes. Personally, I would just use the task’s name and then capitalize the first letter and use that as the class name. Keeping it brief and simple. To do this, we can just use the ucfirst() function. So, it’ll look something like this.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];
	$className = ucfirst($action);

	if(file_exists('toolbar/' . $action . '.php')) {

		// We are good now.
		require_once 'toolbar/' . $action . '.php';

	} else {

		// Error page here again.

	}

} else {

	// Error page here.

}

If someone typed /edit/1, the class name will actually be Edit. If someone typed in /delete/1, the class name will actually be Delete. Next, we’ll dynamically call the class and assign it with a dynamic variable. Something appropriate for the class name and the file name. So we’ll just assign a variable based on the task name. To do this, it’s simple. We just wrap the $action variable around curly braces and then put a $ in front of it to make it a variable. In PHP 7, everything is read from left to right. So in order for us to tell PHP that we want to actually get the name of the variable first, we’ll have to wrap curly braces around it first. If we don’t do that, PHP will execute from left to right. This will actually cause an error since $$action isn’t a thing. By wrapping a curly brace around $action, we tell PHP that we want it to execute this piece first. This in turn will give us something like edit or delete. Next, PHP will then execute from left to right and the end result will actually be something like $edit or $delete.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];
	$className = ucfirst($action);

	if(file_exists('toolbar/' . $action . '.php')) {

		// We are good now.
		require_once 'toolbar/' . $action . '.php';
		${$action} = new $className();

	} else {

		// Error page here again.

	}

} else {

	// Error page here.

}

Next, we’ll have to call the id method so that we can pass in the id and do some cool stuff with it. In order for us to do that, we must make sure that the id method actually exists. We’ll use something called is_callable. Some people prefer method_exists, but we’ll just use is_callable for now.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];
	$className = ucfirst($action);

	if(file_exists('toolbar/' . $action . '.php')) {

		// We are good now.
		require_once 'toolbar/' . $action . '.php';
		${$action} = new $className();

		$callable = [${$action}, 'id'];
		if(is_callable($callable)) {

			// The method is accessible.

		} else {

			// Error page here once more.

		}

	} else {

		// Error page here again.

	}

} else {

	// Error page here.

}

From here, now all we just really need to do is call the actual method and pass in the id. So something like so.

declare(strict_types=1);

if(isset($_GET['action']) AND isset($_GET['id'])) {

	$action = $_GET['action'];
	$id = (int) $_GET['id'];
	$className = ucfirst($action);

	if(file_exists('toolbar/' . $action . '.php')) {

		// We are good now.
		require_once 'toolbar/' . $action . '.php';
		${$action} = new $className();

		$callable = [${$action}, 'id'];
		if(is_callable($callable)) {

			${$action}->id($id);

		} else {

			// Error page here once more.

		}

	} else {

		// Error page here again.

	}

} else {

	// Error page here.

}

We are finally done with the toolbar.php file. Now we have to focus on the task controllers. These controllers are actually really simple. It only requires 1 method and then we can pretty much do whatever we want with the passed in id. So for each task, the controllers are going to be relatively similar.

For edit.

class Edit {

	public function id(int $id = 0) {

		print($id);

	}

}

For delete.

class Delete {

	public function id(int $id = 0) {

		print($id);

	}

}

Now, all we really need to do is the generic basic things such as form submission checking and form validation. Then displaying things and what not. But from here, you can pretty much work out the simple things. This is where you also call your database if you are dealing with one. But you get the gist of it.

But any comments is welcomed even if it’s criticism.