2016-01-01 129 views
3

我原本一直問(並回答)幾次面前的問題1234:我怎麼調用在同一類不同的函數中定義的變量 - 但不能讓下面的工作:訪問變量的CodeIgniter類

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 questioncontroller methods in CodeIgniter work slightly differently from regular PHP class methods評論。 model類也是這種情況:如果是這樣,我需要首先調用test1(並且其他方法中的變量不可訪問),或者有其他我不明白的地方?

活生生的例子

這就是我真正想要做的事情 - 請告訴我,如果有更好的方法來做到這一點!

我要分手了其運行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 - 它會怎麼做呢?

回答

1

術語可能存在一些誤解。

在您的第一個代碼示例中,test1是設置器。如果需要,所有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:
呼喚你的吸附材料(其他地方在你的代碼)之前,先打電話給你的二傳手:

// 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內打電話給你的二傳手。這種感覺jenky,但可能在某些情況下,正確的解決方案:

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

作爲一個側面說明,誰的人不得不維持在幾年前寫的代碼,我可以證明的命名函數的值以描述性/有意義的方式。調用它們的一些變體,並獲得一個有意義的變量名稱,以後再進行故障排除。

製造的例子:

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(); 
    } 
} 
+0

感謝您的解釋(我主要是一個python傢伙 - 而python並不傾向於需要setter/getters)!我仍然不明白爲什麼我在我的問題中提供的鏈接中的例子(例如http://stackoverflow.com/a/2483693/889604)能夠工作 - 這個回答'echo's設置在另一個函數中的變量沒有在類的頂部聲明它或沒有首先使用getter的同一個類 – ChrisW

+0

關鍵在於你在引用的問題結尾處的OP語句中:「在上面的例子中,我想調用$ var這是一個變量**是在前一個函數內定義的**但這不起作用,所以我該如何做到這一點? - 該變量已在前一個函數中定義。所以,大概在OP的代碼中,「setter」函數已經在其他地方被調用了。 –

+0

Eek,對不起 - 我想我剛剛意識到這篇文章裏發生了什麼 - 第一類中的getter在被創建之後(被稱爲「create」類)在第二類*中被調用。所以 - 我想我說的是,調用同一類中定義的變量的唯一方法是使用setter/getter方法?我也用我真正想要做的事情更新了我的問題 - 這是您的選擇4的可接受使用,還是有更好的方法? – ChrisW

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兩兩件事:我已經糾正public $myVar進行正確的初始化,並添加$this->test1()返回設置屬性之前調用的設置方法。

UPDATE

一種更好的方法,以減少的數據庫和方法調用的數量將是:

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對象以數組形式獲取結果並對行進行計數。最後,我們返回包含'array'和'num'索引的test2()$results數組。

從我們的控制器,我們可以調用我們的模型和訪問返回的值是這樣的:

// 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模式的方法調用。我希望這能夠回答你的問題的核心目標。

+0

我不確定這實際上是否回答我的問題 - 它只是重複我的問題的後半部分,表明它可以使用'setter'方法。它也與[這個答案](http://stackoverflow.com/a/2483693/889604) - 所以誰(更)正確?! – ChrisW

+0

我已經解釋了爲什麼您在問題中顯示的第一種方法無效,但您尚未提供足夠的詳細信息來幫助您完成所要做的事情。這很可能是你做錯了。 –

+1

@ErenArdahan我們在這裏使用PHP,並且他使用strtoupper()函數返回,根據PHP文檔,它返回一個字符串,即使輸入變量不存在,爲null或none。 –

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的陳述,他應該接受的答案。

+0

感謝CI特定的示例! – ChrisW