iT邦幫忙

0

PHP物件導向

  • 分享至 

  • xImage

各位大大您好,小弟目前遇到一個問題:
A.php

$hello=new load();
foreach([1,2] as $number){
    $Todo=$hello->ToDoSomthing($number);
    echo Todo;
}

B.php

class load{

public function ToDoSomthing($No){
    return $this->LoadFile($No)->hello();
}
private function LoadFile($classNo){
    require_once $classNo . ".php";
    $UseClass = '';
    switch ($classNo) {
         case "01":
          $UseClass = new \C01\hello();
         break;
         case "02":
          $UseClass = new \C02\hello();
         break;
    }
    return $UseClass;
    }
}

C01.php

namespace C01;
class hello{
    public function() hello{
    return '1';
}
}

C02.php

namespace C02;
class hello{
    public function() hello{
    return '2';
}
}

想透過不同的檔案建立不同的SQL去分類,如上是目前的架構,想請問我還可以怎麼調整會使程式更優美,因為使用起來編輯器會在 return $this->LoadFile($No)->hello();顯示找不到function,但執行卻能正常持行。不知道是不是架構哪裡有誤希望有大大能幫忙解惑。

p.s.若寫的大錯特錯或理解上有誤 請鞭小力點。
/images/emoticon/emoticon06.gif

ide 找不到 function 補個註解就好了,比如 /** @var C01\hello $UserClass */
qpalzm iT邦新手 1 級 ‧ 2022-01-11 08:25:22 檢舉
後來真的改成註解了xd
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
3
淺水員
iT邦大師 6 級 ‧ 2022-01-10 16:53:14
最佳解答

C01 跟 C02 被要求有相同的 function
那麼應該是可以用 interface 來處理

看更多先前的回應...收起先前的回應...
qpalzm iT邦新手 1 級 ‧ 2022-01-10 17:00:05 檢舉

請問如果改成抽象abstract class 呢?

淺水員 iT邦大師 6 級 ‧ 2022-01-10 17:34:27 檢舉

請問如果改成抽象abstract class 呢?

這邊應該也是可以的,例如這樣寫
test.php(A.php)

require('Autoload.php');
$hello = new load();
foreach ([1, 2] as $number) {
    $Todo = $hello->ToDoSomthing($number);
    echo $Todo;
}

Autoload.php (改自B.php)

spl_autoload_register(function ($classname) {
    include $classname . '.php';
});

class load
{
    private $classMap = [
        '01' => \C01::class,
        '02' => \C02::class,
        '1' => \C01::class,
        '2' => \C02::class,
    ];

    public function ToDoSomthing($No)
    {
        return $this->LoadFile($No)->hello();
    }

    private function LoadFile($classNo)
    {
        if (!isset($this->classMap[$classNo])) {
            throw new Exception("classNo error");
        }
        $classname = $this->classMap[$classNo];
        return new $classname;
    }
}

CxxAbstract.php

<?php
abstract class CxxAbstract
{
    abstract public function hello();
}

C01.php

class C01 extends CxxAbstract
{
    public function hello()
    {
        return '1';
    }
}

C02.php
(略)

qpalzm iT邦新手 1 級 ‧ 2022-01-11 08:21:53 檢舉

謝謝大大的解說~/images/emoticon/emoticon41.gif

目前已改成用介面的方式是實作

淺水員 iT邦大師 6 級 ‧ 2022-01-11 09:42:50 檢舉

推薦研究一下 composer 怎麼用
現在很多專案都會用這個做套件管理
require 的部分不大會自己處理了

而其中自動載入的部分也會用到 psr-4 的規則來確定檔案與 class 之間的關係
所以也了解一下 psr-4 比較好

qpalzm iT邦新手 1 級 ‧ 2022-01-11 09:45:32 檢舉

好的,近期已開始研究larval的框架和composer了謝謝您~

淺水員 iT邦大師 6 級 ‧ 2022-01-11 09:52:50 檢舉

(僅供參考)
我以前是看這個教學影片:
PHP 也有 Day #28 - Composer 從入門到實戰 by Shengyou Fan

qpalzm iT邦新手 1 級 ‧ 2022-01-11 10:22:44 檢舉

淺水員非常感謝您!!!!!
/images/emoticon/emoticon41.gif

1
Felix
iT邦研究生 2 級 ‧ 2022-01-10 15:52:42
require_once $classNo . ".php";

這一行的 $classNo 沒有被定義。
我想這裡應該要使用 $No 而不是 $classNo
記得下方的 switch 也要改一下。

題外話,如果是雙引號的字串,則能直接代入變數:

require_once "$classNo.php";
require_once "{$classNo}.php";
qpalzm iT邦新手 1 級 ‧ 2022-01-10 16:21:43 檢舉

謝謝大大的提醒 ,剛剛手誤已修正~
想請問修正後,idea還是提醒還是顯示找不到function。/images/emoticon/emoticon06.gif

3
fillano
iT邦超人 1 級 ‧ 2022-01-11 00:32:58

new後面可以接變數名稱來construct,用起來像這樣:

$classname = '\C01\Hello';
return new $classname();

我調整一下你的例子,讓他稍微多一些泛用性...

Loader.php

<?php
class Loader {
        public function load($ns, $cls) {
                return $this->loadFile($ns, $cls);
        }
        private function loadFile($ns, $cls) {
                require_once "$ns/$cls.php";
                $classname = "\\$ns\\$cls";
                return new $classname();
        }
}

Index.php

<?php
require_once 'Loader.php';

$loader = new Loader();
foreach(['01', '02'] as $num) {
        $obj = $loader->load("C$num", 'Hello');
        echo $obj->hello();
}

/C01/Hello.php

<?php
namespace C01;
class Hello {
        public function hello() {
                return "Hello C01\n";
        }
}

/C02/Hello.php

<?php
namespace C02;
class Hello {
        public function hello() {
                return "Hello C02\n";
        }
}

執行結果像這樣:

$ php -f Index.php
Hello C01
Hello C02

在其他語言需要用Reflection才能做到的事情,在PHP可以用變數來做。

fillano iT邦超人 1 級 ‧ 2022-01-11 00:40:38 檢舉

Loader的地方考慮還不完整(namespace與檔案目錄的對應沒有正確處理),但是知道意思就好。把namespace跟目錄結構對應、class name跟檔名對應的話,不用看程式碼就可以知道程式架構。這樣的convention很方便,所以一些程式語言會刻意這樣實做,例如Java。

qpalzm iT邦新手 1 級 ‧ 2022-01-11 08:24:32 檢舉

謝謝fillano大的解說~當初在學oop也是看您的文章學習~真的也學了不少觀念/images/emoticon/emoticon07.gif

我要發表回答

立即登入回答