iT邦幫忙

0

class 引用外部值?

最近在看書學物件導向 (Laravel 應用)
只是遇到一個問題書上沒教,也沒辦法打關鍵字查谷歌,因此卡住

問題一
就是假設我要實現 class 繼承
一開始的 class 我訂為資料庫連線

class connection {
   var $host = $config['host'];
   var $username = $config['username'];
   var $password = $config['password'];

   $do = new mysqli($host, $username, $password, $config['db']);
}

但是我發現 class 好像無法使用外部值
(如以上會顯示$config為錯誤)

我要依照網域去判別環境
意味著必須為變數
但是在 class 裡面不吃外部值(我知道 public function 可以使用 global)
那我能透過哪判斷他該讀測試資料庫還是正式資料庫呢

問題二
如果以上可行,我 class 裡面的 function 就不需要 global 直接就可以使用繼承 class 裡面的東西了對吧?
只是萬一又有一個變數是外部的,我這個 function 要使用,但我繼承的 class 裡面是沒有這個變數的呢?
一定要使用 global 才可嗎?

新手提問,煩請大大解釋
謝謝

2
浩瀚星空
iT邦大師 1 級 ‧ 2019-05-02 15:24:13
最佳解答

觀念還算不錯,知道不要用global來處理。

一般來說,問題還是在於繼承性及讀取性。

一般如果是設定的方式,可分如下的應用

1.讀檔設定法:
讀檔應用的方式,可以將設定的資料存到一個php內。當你下達connection,先給與你定義的值。
再用incluse的方式來載入對應的設定檔應用。
這算是很早期的做法。一般這招我會教給對物件導向的人還不熟使用。畢竟inclide還算是基礎。
但是如果真想要用物件導向式的方式。盡量還是不要用這樣的設計。

2.繼承值應用法:
一般就是直接將值傳送進去。如

function connection($user,$password,$local,$dbname,$port){

}

3.外部值應用:
這是我比較常用的做法。將config的部份另外設定一個class config
並將其放在init或是global共用的區塊中載入應用。
這樣就可以用 $this->config->db來做取值處理。不需要再做繼承。
只是放在模組內(model)來處理。

還有其它很多種應用的方式,先提供這幾種給你參考。我個人是都用第三種方式就是了。

1
舜~
iT邦好手 1 級 ‧ 2019-05-02 14:24:24
<?php
global $config; /// 加上這行看看
class connection {
// ...(略)
}

global的位置換一下就可以了

如果不使用global的話,就要自行把值傳過來
常見就是
1.建構子 [PHP] 類別的繼承及建構子和解構子
2.新增個function專門接收外部資料

class connection {
   var $config;
   function Init($config){ $this->$config = $config; }
}

3.透過Session、Post、Get、資料庫、存取檔案...

3
Samと可樂快跑
iT邦研究生 1 級 ‧ 2019-05-02 15:24:36
class Connection {

    private $config;

    static function getShared($config) {
        $connection = new Connection();
        $connection->config = $config;
        return $connection;
    }

    function getConfig() {
        return $this->config;
    }

}

用法:

$connection = Connection::getShared(); //有些人習慣名稱叫getInstance()

不過這邊並沒有設置靜態屬性,不會去判定物件是否已經存在。所以不算是Singleton;
Singleton的話:

class Connection {
    static $instance;
    private $config;

    static function getInstance($config = null) {
        if (! $connection = Connection::$instance ) {
            $connection = new Connection();
            Connection::$instance = $connection;
        }

        $connection->setConfig($config);
        return $connection;
    }

    function setConfig($config) {
        if($config != null) {
            $this->config = $config;
        }
    }

    function getConfig() {
        return $this->config;
    }

}

$config = "settingA<br>";

$demoA = Connection::getInstance($config);
echo $demoA->getConfig();

$demoB = Connection::getInstance();
echo $demoB->getConfig();

(剛剛發現有點小錯誤,所以有修正了code)
你會發現你$demoB要是不設定$config的話他就是吃原本$demoA的設定。
因為在靜態全域中只會允許有一個實體。

global要使用的話要僅慎。通常沒非常必要不會做global宣告。
以避免不知道在什麼情形下變數發生了全域參考的問題。

weiclin iT邦高手 4 級 ‧ 2019-05-03 02:54:49 檢舉

我差不多也是這樣弄, 但是你這個範例 $config = "settingA<br>" 太偷懶了吧
/images/emoticon/emoticon10.gif

幫補充一下, 如果只是要給 php 讀的話, 直接用 php array 寫 config 就好:
config.php

if (是網域A) {
    return [
        'db' => [
            'user' => "...",
            'password' => "...",
            .......
        ],
    ];
} else {
    return [/* 給其他網域的設定 */];
}

然後這樣取得 config, 就能達成要給不同設定的功能了:
???.php

$config = require "path/to/config.php";

weiclin
噓(小聲點)………那只是忙裡偷個閒隨便寫一下……

我要發表回答

立即登入回答