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 才可嗎?

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

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
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
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
噓(小聲點)………那只是忙裡偷個閒隨便寫一下……

我要發表回答

立即登入回答