iT邦幫忙

1

[PHP]Class 繼承、建構子的疑難 新手求救

login.php中的getdata()內的getuserkey()和$mysqli都在另外兩個文件,
1.怎樣把兩個不同的class(sql.php和key.php)在另一個class(login.php)上面使用?
2.但是呼叫getuserkey()又需要呼叫db,那在login.php和key.php該怎樣修改?

sql.php

<?php
class db {
    function __construct() {
        $this->conn();
    }
    
    private function conn() {
        $mysqli = new mysqli('localhost', 'root', 'root', 'test');
        return $mysqli;
    }
}

key.php

<?php
class key {
    public function getuserkey() {
        $key = $mysqli->query("SELECT * FROM key")->fetch_assoc()['key'];
        return $key;
    }
}

login.php

<?php
class login {
    public function getdata() {
        $key = getuserkey();
        $data = $mysqli->query("SELECT data FROM data WHERE key='$key'");
        if($data = $data->fetch_assoc()) {
            return $data;
        } else {
            return FALSE;
        }
    }
}
看更多先前的討論...收起先前的討論...
wiseguy iT邦超人 1 級 ‧ 2016-01-18 11:15:23 檢舉
通常來此發問是過程中遇到一個問題點,需要一些提示就可解決。不過看了你的程式,顯然離『懂物件導向』的程度還有一段距離,你要不要先通盤瞭解一下物件導向,再來看你的問題是什麼?要不然別人解釋了,恐怕你還是不懂其所以然。
先從這開始吧:
http://php.net/manual/en/language.oop5.php
fillano iT邦超人 1 級 ‧ 2016-01-18 11:44:01 檢舉
除了物件導向基礎,我覺得還有更基礎的...

不知道樓煮有沒有聽過「include」及「require」?

http://php.net/manual/en/function.include.php

http://php.net/manual/en/function.require.php

另外一個是讓您寫物件導向更方便的:

http://php.net/manual/en/language.oop5.autoload.php

如果要使用別人寫好的library,並且管理當中的依賴性,可以用composer:

https://getcomposer.org/

(靠北,被hack了嗎?怎麼logo配色變成這樣XD
iT邦幫忙MVPfillano提到:
composer

他的Logo會變色
外獅佬 iT邦大師 1 級 ‧ 2016-01-18 12:13:25 檢舉
iT邦幫忙MVPfillano提到:
樓煮

這層樓還有專門管煮的呦.....冷冷
weiclin iT邦高手 4 級 ‧ 2016-01-18 13:51:51 檢舉
送 "封裝" 這兩個字給你當方向
ryo89589 iT邦新手 5 級 ‧ 2016-01-19 00:21:42 檢舉
真心感激各位!!
謝fillano,您幫了我很多呢!!
謝wiseguy的OOP的PHP頁面!
也謝weiclin!

起初我在建構子不懂怎放:
如果是獨立的class(如sql,[不用建構子,就不用弄^^])就懂,但如果要用其他的class(如key用sql//login用sql,key[要建構子,就不知怎弄@@])就亂了......

啟發:

4. 使用類別前,請先用new產生一個>>>實例<<<(如果學過其他物件導向語言,應該會知道這個)
7. login.php:跟key一樣阿,要有地方存$mysqli,才能用它。>>>沒有產生class key的實例前,你沒辦法呼叫他的getuserkey()方法<<<


原來new產生那個叫>>>實例<<<,而用getuserkey()也要用>>>那個實例<<<
特別感激fillano指點!!

已修改:
key.php

private $_sql;
private $_key;

function __construct($sql, $key) {
    $this->_sql = $sql;
    $this->_key = $key;
}


index.php
<?php
require_once 'sql.php';
require_once 'key.php';
require_once 'login.php';

$sql = new db();
$key = new key($sql);
$login = new login($sql, $key);

ryo89589 iT邦新手 5 級 ‧ 2016-01-19 00:22:29 檢舉
最後一個問題,[不過真的謝謝!!]
在index.php,有方法可以省略點new,可以在class弄嗎?


例:e又用到d,d又用到c,c又用到ab,ab才是獨立;除了合成一行,可以在class弄嗎?
$a = new a();
$b = new b();
$c = new c($a, $b);
$d = new d($a, $b, $c);
$e = new e($a, $b, $c, $d);
...


我一定會加油的,因為這為這弄了一大步!![繼續自學中...]
其實不用這樣new到天荒地老………
$db = new db;
$login = new login($db, new key($db));

但是其實你不覺得這樣還是……沒效率了點?
所以其實你也可以直接在建構式裡頭new就好了。
物件生成的方式雖然基礎是從new…可是沒限定你每次都得下new這個指令。

換句話說……何不乾脆讓類別自動生成物件?
<?php
class db {
    
    function getDb(){
        return 'Run';
    }
    
}

class key {
    
    function __construct(db $db)
    {
        $this->db = $db;
    }
    
    function go()
    {
        return $this->db->getDb();
    }
    
    
    static public function instance(db $db)
    {
        return new self(new db);
    }
    
}

$key = key::instance(new db);
echo $key->go();
字數太多,被強迫要分二段。

這只是一個範例。
當然,你也可以讓兩個物件都具備自己生成的方法如下:
<?php
class db {
    
    function getDb(){
        return 'Run';
    }
    
    static public function instance(){
        return new self;
    }
    
}

class key {
    
    function __construct(db $db)
    {
        $this->db = $db;
    }
    
    function go()
    {
        return $this->db->getDb();
    }
    
    
    static public function instance(db $db)
    {
        return new self(new db);
    }
    
}

$key = key::instance(db::instance());
echo $key->go();


另外,我覺得也許你會對傳入的參數$db前面的db會有所疑慮:
 static public function instance(db $db)

那個其實是指定傳入參數的型態
比如你可以限定傳入是數值、字串、陣列或是物件
亦或是指定的類別…我這邊就是指定傳入的類別強制必須是db,如果你傳入別的物件
就會出錯。

我想把這幾件事告訴你,你應該可以從中獲得更多的想法。
最後就是目前其實比較通用的一種coding style
就是class名稱字首大寫。
一般函式駝峰式寫法:
function getAddressOfSingleUser(){
    //這只是個範例,沒事別搞那麼長。
}  


類別定義時:
class GetAddressOfSingleUser {
    //就說了這只是個範例,寫那麼長的話………其實感覺也挺爽的!
}


把一些程式碼風格有所區別會比較好管理。
weiclin iT邦高手 4 級 ‧ 2016-01-19 03:05:12 檢舉
辛苦打這麼多, 怎麼不用回答的..
weiclin iT邦高手 4 級 ‧ 2016-01-19 03:08:27 檢舉
底下有人回你了, 我來幫你喊加油
小財神 iT邦好手 1 級 ‧ 2016-01-19 09:57:43 檢舉
對呀~
ryo89589提到:
login.php中的getdata()內的getuserkey()和$mysqli都在另外兩個文件

人家費大公都這麼詳細回答了…
我就不好意思搶佔他的版面了。
以前我在用知識家時的習慣…
通常只有三種情形我才會搶回答
一個是回答有錯或文不對題
一個是故意廣告
最後一個是有人明明回答,卻又把別人的答案換個文字敘述重寫一次
newkevin iT邦高手 1 級 ‧ 2016-01-19 12:50:25 檢舉
tkdmaf提到:
最後一個是有人明明回答,卻又把別人的答案換個文字敘述重寫一次


其實有時候,這樣比較容易懂吧?
也是對前輩答案,的融會貫通吧,
但是現在的 幾乎只是佔為己有吧?
fillano iT邦超人 1 級 ‧ 2016-01-19 16:41:51 檢舉
我很久沒看PHP的書了,不然應該建議樓煮看本「好」書學會比較快......有沒有人要推書的阿放馬過來

(為什麼寫「好」書...因為爛書頗多...所以我也不太敢推)
PHP設計模式學習手冊 歐萊禮
喔!昨天的補充範例有個地方寫錯了,應該是指接self($db)就好了而不是self(new db)
<?php
class db {
    
    function getDb(){
        return 'Run';
    }
    
    static public function instance(){
        return new self;
    }
    
}

class key {
    
    function __construct(db $db)
    {
        $this->db = $db;
    }
    
    function go()
    {
        return $this->db->getDb();
    }
    
    
    static public function instance(db $db)
    {
        return new self($db);  //改成這樣才對
    }
    
}

$key = key::instance(db::instance());
echo $key->go();
ryo89589 iT邦新手 5 級 ‧ 2016-01-20 01:54:24 檢舉
真心謝謝各位的幫忙!!

謝謝tkdmaf的幫忙!!
修改了的login.php
<?php
class login {
    private $_sql;
    private $_key;

    function __construct(db $sql, key $key) {
        $this->_sql = $sql;
        $this->_key = $key;
    }

    static public function instance(db $sql, key $key)
    {
        return new self($sql, $key);
    }

    public function getdata() {
        $key = $this->_key->getuserkey();
        $data = $this->_sql->query("SELECT data FROM data WHERE key='$key'");
        if($data = $data->fetch_assoc()) {
            return $data;
        } else {
            return FALSE;
        }
    }
}


謝謝weiclin幫我打氣!
之後我會繼續嘗試編寫程式!加油!!!

1 個回答

14
fillano
iT邦超人 1 級 ‧ 2016-01-18 17:47:56
最佳解答

還是回一下好了。

  1. 檔案命名盡量跟class一致,未來做autoload會比較容易
  2. 你要使用哪一個檔案中的程式,只要include/require他就可以
  3. 你這裡完全沒有用到繼承,我就不說了
  4. 使用類別前,請先用new產生一個實例(如果學過其他物件導向語言,應該會知道這個)
  5. sql.php(or db.php):你的class db不把$mysqli傳出來,別人要怎麼用
  6. key.php:class key要有地方存放$mysqli,可以透過__constructor丟進來
  7. login.php:跟key一樣阿,要有地方存$mysqli,才能用它。沒有產生class key的實例前,你沒辦法呼叫他的getuserkey()方法

總之...加油吧

我要發表回答

立即登入回答