📜 ⬆️ ⬇️

Controllers based on reflection mechanisms.

a controller is a specialized entity for managing other entities.
Often use functional controllers based on naming (naming) examples are widely known, for example, Smarty plugins:
smarty_ type_name () as you can see from the documentation, the plugin becomes available if the corresponding functions are declared.

In general, there is a simple controller that searches for a function according to simple rules based on naming.
Often, such called entities want to be encapsulated or otherwise collected and closed into something, resulting in files with a typically functional approach:
mylib.php:
  function mylib_afunc () {};
 function mylib_bfunc () {};
 function mylib_cfunc () {}; 


Of course, this does not guarantee integrity, litters the global namespace, and so on.
It is convenient to procapsulate such things in the class:

  class MyLib {
     static function a () {};
     static function b () {};
     static function c () {};
 } 

')
Further it is not difficult to understand how to make a controller based on method_exists, to which the first argument can be given the name of the container class. As a rule, fantasy stops there, but many more benefits can be derived from the object paradigm:
I will proceed to the consideration of a specific task immediately, so that it would be easier to understand the idea by example.
we want to implement a simple controller for selecting the displayed module page

for starters, I'll show you the worst version of how they do it:
  swich $ _GET ['action'] {
     case: "a" ...
     case: "b" ...
     case: "c" ...
 } 

only variants with if-elseif-else are worse, so that such a controller does not write, for example, as in smarti based on nimenge:

  if (function_exists ('myAction _'. $ _ GET ['action']))
     call_user_func ('myAction _'. $ _ GET ['action']); 


but I will describe a slightly different approach, more formal:
here is the code in color: dumpz.org/2513

and here is just a code so as not to run:

 abstract class Module {
    public final function buildPage ($ action) {
   	 do {
   		 // you cannot call functions that start with an underscore
   		 // (common agreement to consider them private)
		 if (substr ($ action, 0, 1) == '_' or empty ($ action)) 
			 break;
		 // you can not call the functions described in the abstract class, they are for the system
		 if (method_exists (__ CLASS__, $ action))
			 break;
		 if (! method_exists ($ this, $ action))
			 break;
		 $ method = new ReflectionMethod ($ this, $ action);
		 // only public methods are available
		 if (! $ method-> isPublic ())
			 break;
		 return $ this -> $ action ();
   	 } while (false);	
	 return $ this-> error404 ();
    }
    public function error404 () {
   		 echo 'there is no such page in the system';
    }
 }

 class ExampleModule extends Module {
	 function hello () {
		 echo 'hello World!';
	 }
	
	 function test () {
		 echo 'Test !!!';
	 }
	 protected function inner () {
		 echo 'this internal function is not available to the controller!';
	 }
 }

 $ module = new ExampleModule ();
 $ module-> buildPage (isset ($ _ GET ['action'])? $ _ GET ['action']: '');


the controller is the " buildPage " function

so if you call the script
example.com/?action=hello
then you’ll get to the hello function,
and this is not how the controller will not miss you:
example.com/?action=inner

examples of the use of such mass controllers - everything is limited only by your imagination, they successfully replace swich and if-else cascades, provide a clear layer of abstraction, are quite fast and easily expandable.

further development of the idea of ​​such controllers lies in the use of inheritance , for example, if you find out that your user is registered, then nothing prevents you from creating a class for registered
 class UserExampleModule extends ExampleModule {
      function hello () {
          echo 'hello registered user!';
      }
 }

and when creating an object, write:
 if (authorization check)
     $ module = new UserExampleModule ();
 else
     $ module = new ExampleModule ();

then for authorized users, the UserExampleModule class will already be used to create a module object in which the controller will look for a function.

In general, this is all I wanted to tell ^ _ ^, then I’ll tell you just about the idea of ​​this method.
In the first I “invented” this wheel 2 years ago (for myself, although the world knew it quite a while), it turned out that this approach is used by some western programmers, until now I see tons of code that do not even use simple controllers on naming; instead, for some reason, programmers are tempted to write HUGE swich, I urge you not to do so -), I hope this topic will help you.

Thank you all, do not judge strictly!

Source: https://habr.com/ru/post/39739/


All Articles