Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define two functions, or branch within one?

Tags:

function

php

I was reading about how to detect the encoding of a file in PHP, and on some blog or somewhere, it was suggested to do this:

if (function_exists('mb_detect_encoding')) {
    function is_utf8($str) {
        // do stuff using the mb* libraries
    }
} else {
    function is_utf8($str) {
        // do stuff manually
    }
}

To me this feels very messy, and could be replaced with this:

function is_utf8($str) {
    if (...) {
        // mb stuff here
    } else {
        // manual stuff here
    }
}

However, I can also see that it also has some benefits. Depending how complicated the if statement is, and how often the function is called, this might be much more efficient. My question is this: At what point would you consider splitting a function into two like in the first example? Are there any other pros/cons that I've missed?

Edit: Please don't get hung up on the example here, the question is about this practice in general.

like image 279
nickf Avatar asked Dec 08 '25 10:12

nickf


2 Answers

My gut reaction is to go with a single declaration of the is_utf8 function. The PHP engine is mighty good at optimization and the overhead of multiple calls to function_exists() should be negligible.

like image 195
leepowers Avatar answered Dec 10 '25 02:12

leepowers


A good practice, maybe not in that case, but in general might involve the use of OOP (objects) with factory methods.

class my_utf8 
{
  // A static method that determine what object to create
  public static function factory() {
    if (function_exists('mb_detect_encoding')) {
      return new my_utf8_with_mb;
    } else {
      return new my_utf8_without_mb;
    }
  }
}

class my_utf8_with_mb extends my_utf8 {
    public function is_utf8($str) {
        // do stuff using the mb* libraries
    }
}

class my_utf8_without_mb extends my_utf8 {
    public function is_utf8($str) {
        // do stuff without the mb* libraries
    }
}

And in your application :

global $myUtfInstance;
// Call once
$myUtfInstance = my_utf8::factory();

// later and forever...
$myUtfInstance->is_utf8($str);

You could also involve a singleton pattern depending on what you do. It does not skip the IF but eliminate the need of a global variable.

class my_utf8 
{
  private static $instance;

  public static function factory() {
    if (function_exists('mb_detect_encoding')) {
      return new my_utf8_with_mb;
    } else {
      return new my_utf8_without_mb;
    }
  }


  public static function getInstance()
  {
    if (!self::$instance) {
      self::$instance = self::factory();
    }

    return self::$instance;
  } 
}

And in your code :

my_utf8::getInstance()->is_utf8($str);
like image 23
Pmax Avatar answered Dec 10 '25 02:12

Pmax



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!