Frage

Maybe I'm not getting the whole trait system so I thought I'd ask StackOverFlow.

I made my first trait...

<?php
trait MY_Stat
{   
  var $dex;
  var $int;
  var $str;
}
?>

I can't manage to make it work with my class whatsoever ( in another file ) ....

class MY_Mobile
{
  use MY_Stat;

  public function __construct($params = NULL)
  {     
    var_dump($this);
  }
}

I'm always hitting this wall :

Fatal error: Trait 'MY_Trait' not found in ...\wamp\www\game\application\libraries\MY_Mobile.php

I would like to have this trait in many classes, namely, Mobiles, Items, etc... Am I supposed to have the definition of the trait in the same file as the class ?

On a sidenote, if you're using codeigniter, how did you manage to make it load, are you setting your traits into a helper file, library file... ?

War es hilfreich?

Lösung

Well you can workout this problem by doing something like this:

Path:

application/helpers/your-trait-class.php

Contents:

<?php
if (!trait_exists('MY_Stat')) {
    trait MY_Stat
    {
        public $dex;
        public $int;
        public $str;
    }
}

In your library just include the trait class (as i said) manually. After the !defined('BASEPATH'); line.

Your Library:

include APPPATH . 'helpers/your-trait-class.php';

class YourLibrary {
    use MY_Stat;

and use trait class properties within your library methods like this:

$this->dex = 0.1;
$this->int = 1;
$this->str = 'Hello';

Andere Tipps

Another alternative that works for me.. where model_base is in the model folder

@include_once ('model_base.php');  
class device_token extends CI_Model {

        // PHP 5.4 Traits
        use model_base;

I got this answer from somewhere, now I don't remember from where. anyway

in models folder, create a file named trait_autoloader.php

<?php 
defined('BASEPATH') OR exit('No direct access to script is allowed');

class trait_autoloader{
    public function __construct(){
        return $this->init_autoloader();
    }
    private function init_autoloader(){
        spl_autoload_register(function($classname){
            if(strpos($classname, 'trait') !== false){
                strtolower($classname);
                require('application/traits/'.$classname.'.php');
            }
        });
    }
}

Now that you are done with it open autoload file in config folder in applications folder and put 'trait_autoloader' in the following line,

autoload['model'] = array( 'trait_autoloader' );
 

In applications folder, create a folder named traits and put your traits in that folder, caution: do use 'trait' prefix for all the files in that folder. In this case I used a simple file with name traitFunction.php

<?php 
defined('BASEPATH') OR exit('No direct access to script is allowed');

trait traitFunction{
    public function FunctionName(){
       //Function Body
    }
}

Now that you are done with it. put the following line in any model class you want and they will work fine.

use traitFunction;

Do remember, that this function only works with models.

Taking advantage of spl_autoload_register I had to make a small modification in the codeigniter index.php file

Codeigniter index.php

function load_traits($traits)
{
    $traits_found = [];
    $traitsBasePath = APPPATH .'traits';

    find_trait($traitsBasePath, $traits, $traits_found);
    
    foreach ($traits_found as $found)
        include_once $found;
}




function find_trait($dir, $searchForTrait, &$found)
{
    if(is_string($searchForTrait))
    {
        $dirHandle = opendir($dir);

        if($dirHandle !== FALSE)
        {
            while (false !== ($entry = readdir($dirHandle)))
                if($entry != '.' && $entry != '..')
                    if(is_dir($dir. '/' .$entry))
                        find_trait($dir. DIRECTORY_SEPARATOR .$entry, $searchForTrait, $found);
                    else
                        if(strpos($dir. DIRECTORY_SEPARATOR .$entry, 
                            str_replace("/", DIRECTORY_SEPARATOR, $searchForTrait . '.php')) !== FALSE)
                                array_push($found, $dir. DIRECTORY_SEPARATOR .$entry);
        }
        else
            die("Traits directory does not exists");
    }
    else if(is_array($searchForTrait))
    {
        $dirHandle = opendir($dir);

        if($dirHandle !== FALSE)
        {
            while (false !== ($entry = readdir($dirHandle)))
                if($entry != '.' && $entry != '..')
                    foreach ($searchForTrait as $sTrait) {
                        if(is_dir($dir. '/' .$entry))
                            find_trait($dir. DIRECTORY_SEPARATOR .$entry, $sTrait, $found);
                        else
                            if(strpos($dir. DIRECTORY_SEPARATOR .$entry, 
                                str_replace("/",
                                    DIRECTORY_SEPARATOR, 
                                        $sTrait . '.php')) !== FALSE)
                                            array_push($found, $dir. DIRECTORY_SEPARATOR .$entry);
                    }
                    
        }
        else
            die("Traits directory does not exists");
    }
    else
        die("Parameter must be string or array");
}


spl_autoload_register(function($traitname) {
    load_traits($traitname);
});

Having saying that, you must to create a traits folder into codeigniter application directory and create your traits there.

How do i use this?

In any controller you just use it as follows

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Store extends CI_Controller {

    use test_trait;

}

When use test_trait the file test_trait.php will be searched in traits directory. If the file is found will be automatically included

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top