0

Is there a way to define few similar php function dynamically in a manner like

define('MAX_LOG_LEVEL', 10);

_log_level( $string, $level = 0 ) {
   global $loglevel;
   if( $level >= $loglevel ) {
     file_put_contents(...);
   }
}

for($level = 0; $level < MAX_LOG_LEVEL; $level++) {
   function _log$level( $string ) {
      _log_level( $string, $level );
   }
}

that's because i have to create my own log routines and to quickly add an log information on demand.

I know the php built in create_function that do not really do what i exactly want because will be necessary to import the reference variable in the function/method that use that

I can't also use the eval() function as explained in this question since it is disabled on the final application hosting.

Community
  • 1
  • 1
CaSUaL
  • 154
  • 6
  • 1
    Explain pls, what you want to achieve? From your example - functions _log0, _log1,... _log9, which calls _log_level($s, 0..9)? – S Korolev Jan 30 '14 at 11:46
  • Why are you choosing to do it this way instead of just one function that takes the level + string as an argument? – andy Jan 30 '14 at 11:46
  • Aliases, such as Python's `Logger().debug()`, `.info()`, `.warn()`, `.error()`, and `.critical()`. – tyteen4a03 Jan 30 '14 at 11:48
  • 2
    Why not use more descriptive terms like debug, info, warning, error, fatal, etc.? – Ja͢ck Jan 30 '14 at 11:48
  • 1
    @andy: simply i think is more elegant have a `_log0( something )` instead of `_log(0, something)` – CaSUaL Jan 30 '14 at 11:50
  • 1
    @user3025491, sorry but in common practice _log0().._log9() is far less elegant than _log(0..9,). It's has a real sense if you have meaningful names like `.debug(), .info(), .warn(), .error(), and .critical()` as @tyteen4a03 wrote. – S Korolev Jan 30 '14 at 11:58
  • 1
    Well it's not because you end up clogging the function spaces and it's nowhere near as flexible as the latter. If anything it's 10x worse. – andy Jan 30 '14 at 11:59
  • @andy I had not thought about that! – CaSUaL Jan 30 '14 at 12:06
  • see also the answers to "How can I create a function dynamically?" https://stackoverflow.com/questions/8549496/how-can-i-create-a-function-dynamically – Kai Carver Dec 28 '22 at 10:59

2 Answers2

3

One way to do it is to assign an anonymous function to a variable and call it like so:

foreach (range(1, 9) as $i)
{

  ${'_log' . $i} = function($string) use ($i)
  {
    echo 'Log ' . $i . ': ' . $string;
  };

}

// Outputs Log 9: Test
$_log9('Test');

Another possibility is to use eval (although you can't use it on your current application it might be possible in future environments):

foreach (range(1, 9) as $i)
{

  eval('

    function _log' . $i . '($string)
    {
      echo \'Log ' . $i . ': \' . $string;
    }

  ');

}

// Outputs Log 9: Test
_log9('Test');

If using this latter method take note of the warning in the manual:

Caution The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.

However, as others have mentioned in the comments, it is perhaps best to not define a unique function for each log-level: instead define a single function with the log-level as a parameter:

function _log($i, $string)
{
  echo 'Log ' . $i . ': ' . $string;
}

// Outputs Log 9: Test
_log(9, 'Test');

A further extension to this is to define the log levels to make it clearer to both yourself and to future programmers what exactly is being logged:

define('_LOG_CRITICAL_ERROR', 9);

function _log($i, $string)
{
  echo 'Log ' . $i . ': ' . $string;
}

// Outputs Log 9: Test
_log(_LOG_CRITICAL_ERROR, 'Test');
Michael
  • 11,912
  • 6
  • 49
  • 64
0

Yes, it is possible; you can do this:

$function = '_log' . $level;
$function($string);

This is known as a variable function.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 1
    this is not I want to achieve: I want to call exactely _log0, _log1, ... Not to have a pointer to them – CaSUaL Jan 30 '14 at 11:57
  • My code example _does_ call the function with the specified log level in its name. If you want to call many of them, wrap the above in a loop. – halfer Jan 30 '14 at 12:01