各位大大您好,小弟目前遇到一個問題:
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.若寫的大錯特錯或理解上有誤 請鞭小力點。
C01 跟 C02 被要求有相同的 function
那麼應該是可以用 interface 來處理
請問如果改成抽象abstract class 呢?
請問如果改成抽象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
(略)
謝謝大大的解說~
目前已改成用介面的方式是實作
推薦研究一下 composer 怎麼用
現在很多專案都會用這個做套件管理
require 的部分不大會自己處理了
而其中自動載入的部分也會用到 psr-4 的規則來確定檔案與 class 之間的關係
所以也了解一下 psr-4 比較好
好的,近期已開始研究larval的框架和composer了謝謝您~
(僅供參考)
我以前是看這個教學影片:
PHP 也有 Day #28 - Composer 從入門到實戰 by Shengyou Fan
淺水員非常感謝您!!!!!
require_once $classNo . ".php";
這一行的 $classNo
沒有被定義。
我想這裡應該要使用 $No
而不是 $classNo
。
記得下方的 switch
也要改一下。
題外話,如果是雙引號的字串,則能直接代入變數:
require_once "$classNo.php";
require_once "{$classNo}.php";
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可以用變數來做。