Tutorials PHP Extending and Importing Functions into Classes Using Traits

Extending and Importing Functions into Classes Using Traits

Today we'll talk more about classes. Before we begin, make sure you read up on PHP Class basics.

What are traits?

In the abovementioned tutorial, I explained what classes are, and how to create an umbrella class and have multiple children that extends from it. So what if you need a class that imports functions from multiple sources?

The obvious (but incorrect) way to extend classes

Your first attempt after running into this issue is probably to just include or require files with methods into your classes.

File: extend.php

function foo() {
  return 'foo';
}

File: class.php

class myclass {
  require_once 'extend.php';
  
  function bar() {
    return 'bar';
  }
}

File: page.php

require_once 'class.php';
$class = new myclass();
$foo = $class->foo();
echo $foo;

This simply does not work. You get a PHP error, and probably spent an hour smacking your head on the table before going for one of the first three options.

First option: create a class wrapper function

You can't require a file with functions directly in a class, but you can do it inside a class' function.

File: extend.php

function foo() {
  return 'foo';
}

File: class.php

class myclass {
  function myfoo() {
    require_once 'extend.php';
    return foo();
  }
  function bar() {
    return 'bar';
  }
}

File: page.php

require_once 'class.php';
$class = new myclass();
$foo = $class->myfoo();
echo $foo;

This works. However, the foo function can only be used in myfoo scope. If you add another function inside myclass, it can't use the foo function unless you include it again. You also can't directly call it from page.php.

Second option: chain extends

You could wrap those extended functions with classes, then extend them, and have your main class at the very end of that chain.

File: extend.php

class foo {
  function foo() {
    return 'foo';
  }
}

File: class.php

require_once 'extend.php';
class myclass extends foo {
  
  function bar() {
    return 'bar';
  }
}

File: page.php

require_once 'class.php';
$class = new myclass();
$foo = $class->foo();
echo $foo;

This option is fine as well, as long as it doesn't cause any catch 22 issues. One problem is that for logic, organization, and sanity's sake, sometimes it doesn't make sense for the "parent" to be "under" the children submodules. The biggest problem is that a class can only extend a single class. If you want to separate it into ten files, you will have to extend, and extend, and extend, ect. I just pity the next guy who has to debug this thing after you leave.

Third option: put all your functions into one file

The tried and true, simple, and obvious solution.

File: class.php

class myclass {
  function foo() {
    return 'foo';
  }
  function bar() {
    return 'bar';
  }
}

File: page.php

require_once 'class.php';
$class = new myclass();
$foo = $class->foo();
echo $foo;

This is perfectly fine for smaller classes. However, if you have a class with a hundred functions, you're going to end up with one big file. This becomes an even bigger issue if you're on a team with multiple developers using git to push fixes to the same file; you're going to be in merge conflict hell.

Traits: The proper way to import classes

Let's go back to the failed attempt. Logically, it's simple and it should work, but it doesn't. Why? It's just missing that last, tiny, piece of the puzzle.

Traits allows classes to use functions from different files. You can create proper extensions for your classes. This also puts all of your imported functions into the scope of the class, so you can call them as if they were actually class functions.

File: extend.php

trait mytrait {
  function foo() {
    return 'foo';
  }
}

File: class.php

require_once 'extend.php';
class myclass {
  USE mytrait;
  
  
  function myfoo() {
    if ($this->foo() == 'foo') {
      $result = 'This is foo';
    } else {
      $result = 'This is not foo';
    }
    return $result;
  }
  function bar() {
    return 'bar';
  }
}

File: page.php

require_once 'class.php';
$class = new myclass();
echo $class->foo(); // "foo"
echo $class->myfoo(); // "This is foo"

That's all for this tutorial. I hope this helps you all to organize your code better.

Posted by on . Category: PHP


Comments

No comments posted yet

You need to register or login to post new comments.