在 1,2,3,4 之前,我已经多次询问(并回答)了我的问题:如何在同一个类中调用在不同函数中定义的变量 - 但无法使以下内容起作用:
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 - 它还会怎样做?
答案 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次模态方法调用。我希望这能解决你问题的核心目标。