0

I have been programming for a number of years now and in PHP for about 4 of those years. I have always wondered what is the best approach when it comes your program deciding what action to take based on a user action.

Let me narrow this down a little bit. I have a small custom built CMS running, one of the pages allows an admin to view and edit user account details such as name, generate a new password, change payment dates and so on.

I have a number of different actions here:

  • View all users
  • View single user
  • View users (search string)
  • Edit user
    • Edit Subscription
    • Edit Name
    • Etc
  • Delete User
  • Blacklist

For all of these actions i provide a let with GET data, for exampele:

<a href="users.php?action=show_user&uid=12">User A</a>

The links for the other things like editing a user would be "action=edit_subscription" for example.

When My page loads i usually use an IF ELSE statement to check if an action is present before doing on.

if($_GET['action'] == "show_user"){
}
else if($_GET['action'] == "edit_subscription"){
}

Once the program matches the action it checks for other data such as UID and then sends that data off into a classes to be processed. Sometimes this can feel a little long winded and can be a little difficult to debug.

I don't know if this is the best way of doing it, i was recently looking into using a switch statement and wondered if this would be better but I'm not sure if it.

So if there a better way for me to achieve this selection process, maybe some sort of pattern that can be used?

Once last point is that i am trying to keep everything in once file (apart from classes) so the HTML and the PHP for matching actions are all in the same .php file, also not 100% sure if this is best practice as well.

Thanks for your time.

1

I recommend looking at the router code in most modern MVC frameworks. The prevailing approach is to use reflection to invoke a particular function named after the action.

Here's the relevant code from Yii:

Or from Laravel:

/**
 * Execute an action on the controller.
 *
 * @param  string  $method
 * @param  array   $parameters
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function callAction($method, $parameters)
{
    return call_user_func_array(array($this, $method), $parameters);
}

https://github.com/laravel/framework/blob/5.0/src/Illuminate/Routing/Controller.php#L246

In the Yii example it's looking for a function within the class called action<action name> and calling it if it exists. For example if you invoked the ViewUsers actions it would call the actionViewUsers() function. For friendly URLs there's also often a layer above that maps a path to a controller/action combination.

The advantages of this are numerous:

  • It avoids massive and unmanageable case or if statements
  • It keeps variables limited to the scope of their action function
  • The mapping of action -> function is done dynamically so you don't need to maintain a list of these mappings
  • Not even close to how laravel (or other "prevailing") frameworks work. A typical laravel route looks like: Route::get('user/{id}', 'UserController@showProfile'); It's worth looking at the documentation: laravel.com/docs/5.0/routing – Cerad Mar 28 '15 at 1:20
  • @Cerad defining routes that way is generally just another layer of indirection to map a path to a controller/action combo. If you use implicit controllers they will be invoked in the way I described: laravel.com/docs/4.2/controllers#implicit-controllers My specific example using the "action" prefix is Yii specific though, and I've edited my post to clarify. – thexacre Mar 28 '15 at 1:38
0

If you want to get fancy, you could consider a jump table.

Just have an array where the the key is "show_user", "edit_subscription", etc, and the corresponding value is a function to be called. After declaring your array, the actual code is just a single statement to call the function.

I don't have a PHP IDE at the moment, to code it for you, but you can base on the C example.

From memory, something like

$func = myArray[$_GET['action']];
$func();
  • 1
    You don't need a lookup table, most MVC frameworks have a dynamic association between action name and function name. – thexacre Mar 27 '15 at 12:47
  • Hardly worth the downvote though, was it? I just expected a lot of if vs switch discussion & thought I'd throw in a rarely considered alternative. It's certainyl valid & maybe OP, even he doesn't use it now, will have learned something that he can use elsewhere in future. – Mawg Mar 27 '15 at 12:50
0

I think, you are looking for the Routing component for your code. The code I linked is rather individual code library used and provided by Symfony2 framework.

You could inspect approaches it uses to configure and determine routes and controllers for them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.