访问CodeIgniter类中的变量

时间:2016-01-01 13:14:51

标签: php codeigniter

1234 之前,我已经多次询问(并回答)了我的问题:如何在同一个类中调用在不同函数中定义的变量 - 但无法使以下内容起作用:

class my_model extends CI_Model {

  public $myvar;

  public function test1()
  {
    $this->myvar = "Hello world";
  }

  public function test2()
  {
    return strtoupper($this->myvar);
    //And have tried:
    // return my_model::test1()->$myvar
  }

}

更改test1以充当setter函数(并调用该函数来访问变量)确实有效;将我的test1更改为:

public test1()
{
  $this->myvar = "Hello world";
  return $this->myvar;
}

test2

public function test2()
{
  $a = $this->test1();
  return strtoupper($a);
} 

This question的评论为controller methods in CodeIgniter work slightly differently from regular PHP class methods。这也是model类的情况:如果是这样,我需要首先调用test1(并且其他方法中的变量不可访问),或者是否还有其他内容#39;我没理解?!

现实生活中的例子

这就是我实际上要做的事情 - 请告诉我是否有更好的方法来做到这一点!

我打算拆分运行select *查询的方法和返回count的查询,因为我使用了CI QueryBuilder这似乎是一个明显的解决方案:

class my_model extends CI_Model {

  public function __construct()
  {
    $this->load->database();
  }

  public function test1()
  {
    return $this->db->get('Table1');
  }

  public function test2()
  {
    return $this->test1()->result_array();
  }

  public function test3()
  {
    return $this->test1()->num_rows();
  }
}

然而,cale b发表评论说这可能会感觉有点 jenky - 它还会怎样做?

3 个答案:

答案 0 :(得分:1)

可能会对术语产生一些误解。

在您的第一个代码示例中,test1 是一个setter 。应该做的所有setter都设置了一个类变量 - 如果需要,可能会接受该值。塞特斯不一定会回报任何东西。

示例:

// This is an example of a setter
$this->setMyVar( $var ) {
    $this->myVar = $var;
}

在您的第二个代码示例中,您实际上已将test同时设为 setter和getter - 首先设置值,然后返回值:

// This is an example of a setter AND a getter in one
$this->setMyVar( $var ) {
    $this->myVar = $var;
    return $this->myVar;
}

现在,回到你的第一个例子,你的问题:
如你所说 - 它不起作用的原因是因为getter方法(test2)试图从类变量中获取一个值,但尚未设置类变量。

因此,必须首先设置类变量,不知何故,某处。

因此,要修改您的第一个示例代码以使其正常工作,您可以进行四种可能的更改之一:

选项1:
在类的顶部使用所需的值声明您的变量:     public $myvar = 'Hello World';

选项2:
在调用getter(代码中的其他位置)之前,请先调用setter:

// Where used inside of some other function where you need my_model->myval
my_model->test1();
$value = my_model->test2();

选项3:
在构造函数中设置值。将此代码添加到类的顶部将导致在构造类时立即填充变量:

public function __construct() {
    $this->myvar = 'Hello World';
}

选项4: 或者,从你的getter中调用你的setter。这感觉很怪,但在某些情况下可能是正确的解决方案:

 public function test2() {  
    // First call test1 to set the variable
    $this->test1();
    // Now $this->myvar has a value, so return it
    return $this->myvar;
 }

作为旁注,作为必须维护多年前编写的代码的人,我可以用描述性/有意义的方式证明命名函数的价值。将它们称为set和get的一些变体,以及有意义的变量名称,有助于以后进行故障排除。

制作示例:

class my_model extends CI_Model {

    // Flag for debug.  When true, output debug messages
    public $debug;

    public function setDebug( $debug = TRUE ) {
        $this->debug = $debug;
    }

    public function getDebug() {
        return $this->debug;    
    }

    // ... other class methods here ...
}

修改
根据对问题的修订,我将对问题中添加的代码进行这些(潜在)调整:

class my_model extends CI_Model {

  private $results = FALSE;

  public function __construct()
  {
    $this->load->database();
  }

  private function load_results()
  {
    // Could use or remove the logic here, if data remains constant across a single page load keep it, if not, remove it
    // Only hit the database if the $results haven't yet been loaded
    if ( $this->results === FALSE ) {
        $this->results = $this->db->get('Table1');
    }
  }

  public function test2()
  {
    $this->load_results();
    return $this->results->result_array();
  }

  public function test3()
  {
    $this->load_results();
    return $this->results->num_rows();
  }
}

答案 1 :(得分:1)

cale_b为您提供正确的答案。我的意图是以不同的方式说同样的事情。

你的班级

class my_model extends CI_Model
{
  public $myvar;

  public function test1()
  {
    $this->myvar = "Hello world";
  }

  public function test2()
  {
    return strtoupper($this->myvar);
  }
}

在你调用test1()之前,你必须调用test2(),因为$ myvar在执行test1()之前没有给出一个值(设置等于某个值)。

有多种方法可以完成赋予$myvar值的任务。

声明

时设置默认值
class my_model extends CI_Model
{
  public $myvar = 'Hello World';

  public function test1()
  { 
    ...

在下一个示例中,$myvar在类构造函数中设置,该构造函数与上面的函数或多或少完全相同。我还宣布'setter'和'getter'函数。请注意,我将$myvar设为私有,原因将在使用示例中说明。

class Test_m extends CI_Model
{
  private $myvar;

  public function __construct()
  {
    parent::__construct();
    $this->myvar = "Hello world";
  }

  //a 'setter'
  public function set_myvar($newValue)
  {
    $this->myvar = $newValue;
  }

  //a 'getter'
  public function get_myvar()
  {
    return strtoupper($this->myvar);
  }

}

现在举一个使用示例。这是一个控制器

class Teststuff extends CI_Controller
{

  public function __construct()
  {
    parent::__construct();
    $this->load->model('test_m');
  }

  function index()
  {
    echo $this->test_m->get_myvar()."<br>";  //outputs HELLO WORLD

    //change the value of $myvar
    $this->test_m->set_myvar("Hello Stackoverflow");
    echo $this->test_m->get_myvar()."<br>";  //outputs HELLO STACKOVERFLOW

    //try to access $myvar directly
    echo $this->test_m->myvar;
    //produces a PHP error "Undefined property: Teststuff::$myvar"
  }
}

错误是因为$myvar是私有的。将Test_m中的声明更改为public $myvar;,输出将为“Hello Stackoverflow”。

同样,这重申了cale_b所说的内容,他应该得到接受的答案。

答案 2 :(得分:0)

您无法理解的是,在第一个示例中,您不会运行test1(),因此myVar属性保持为空,因此在test2()时会得到一个空字符串被称为。

以下是它的运作方式:

class my_model extends CI_Model {

    public $myVar;

    public function test1()
    {
        $this->myVar = "Hello world";
    }

    public function test2()
    {
        $this->test1();
        return strtoupper($this->myVar);
        //And have tried:
        // return my_model::test1()->$myVar
    }

}

Notie 2件事:我已更正public $myVar以正确初始化并添加$this->test1()以在返回设置属性之前调用设置方法。

<强>更新

减少数据库和方法调用次数的更好方法是:

class MY_Model extends CI_Model {

  public function __construct()
  {
    $this->load->database();
  }

  public function test1()
  {
    return $this->db->get('Table1');
  }

  public function test2()
  {
    // Fetch the database and put the result into a test1 object
    $test1 = $this->test1();
    // Get the results array from the test1 object into an array
    $results['array'] = $test1->result_array();
    // Also get the number of rows value from the test1 object
    $results['num'] = $test1->num_rows();
    // Return the results array which contains an 'array' and 'num' indexes
    return $results;
  }
}

在此示例中,test1变量一次调用$this->test1()方法,以对象形式返回数据库结果。然后,我们只需使用test1对象以数组形式获取结果并计算行数。最后,我们从$results返回test2()数组,其中包含&#39;数组&#39;和&#39; num&#39;索引。

从我们的控制器,我们可以调用我们的模型并访问返回值:

// Load our modal and connect to database
$this->load->model('my_model', 'model', TRUE);
// Perform user registration with form supplied data
$test2 = $model->model->test2();

print_r($test2['array']);
echo $test2['num'];

总共我们做了1次数据库调用和2次模型方法调用,而不是2次数据库调用和3次模态方法调用。我希望这能解决你问题的核心目标。