最近在研究laravel的服務容器概念,
文章:https://laravel-china.org/topics/789/laravel-learning-notes-the-magic-of-the-service-container
有一個疑問不是很理解,麻煩各位大大說明
使用的是Laravel 5.2版本。
我現在有一個controller SuperModuleFactoryController.php。
SuperModuleFactoryController.php 裡面會有兩個不同的class
SuperModuleFactoryController 跟 XPower 這兩個class 。
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\SuperModuleFactoryController;
use App\Http\Controllers\XPower;
use Illuminate\Routing\Controller as BaseController;
class SuperModuleFactoryController extends BaseController
{
public function makeModule($moduleName, $options)
{
switch ($moduleName) {
case 'Fight': return new Fight($options[0], $options[1]);
case 'Force': return new Force($options[0]);
case 'Shot': return new Shot($options[0], $options[1],
$options[2]);
}
}
}
interface SuperModuleInterface
{
/**
* 超能力激活方法
*
* 任何一个超能力都得有该方法,并拥有一个参数
*@param array $target 针对目标,可以是一个或多个,自己或他人
*/
public function activate(array $target);
}
/**
* X-超能量
*/
class XPower extends BaseController implements SuperModuleInterface
{
public function activate(array $target)
{
// 这只是个例子。。具体自行脑补
}
}
/**
* 终极炸弹 (就这么俗)
*/
class UltraBomb implements SuperModuleInterface
{
public function activate(array $target)
{
// 这只是个例子。。具体自行脑补
}
}
class Fight
{
protected $speed;
protected $holdtime;
public function __construct($speed, $holdtime) {
$this->speed = $speed;
$this->holdtime = $holdtime;
}
}
class Force
{
protected $force;
public function __construct($force) {
$this->force = $force;
}
}
class Shot
{
protected $atk;
protected $range;
protected $limit;
public function __construct($atk, $range, $limit) {
$this->atk = $atk;
$this->range = $range;
$this->limit = $limit;
}
}
我想要在另一個控制器 TestController.php檔案裡面,
使用SuperModuleFactoryController.php 檔案裡面的兩個不同class。
class XPower
class SuperModuleFactoryController
所以我在TestController.php檔案裡面
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\TestController;
use App\Http\Controllers\SuperModuleFactoryController;
use App\Http\Controllers\SupermanController;
class TestController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function __construct()
{
$this->middleware('web');
}
public static function superman()
{
// 超能力模组
$superModule = new XPower;
//這邊會顯示 Class 'App\Http\Controllers\XPower' not found
}
}
如果我需要 new 另一個class XPower 要怎麼做呢?$superModule = new XPower;
laravel會顯示
Class 'App\Http\Controllers\XPower' not found
PS:如果一個class 一個controller 可以解決,
在SuperModuleFactoryController.php 底下使用兩個不同的class也可以解決。
但如果要跨不同的controller 在laravel 5.2的架構下,要怎麼寫才是對的呢?
在不同的controller (TestController.php)
呼叫另一個SuperModuleFactoryController (SuperModuleFactoryController.php)
底下的兩個不同class要怎麼做呢?
Laravel Controller 用的是 Composer 的 Autoloading,採用的是 PSR-4 標準。這點可以從 composer.json
中看到:
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
}
所以你只要按照規定的地方放類別檔案,就可以自動載入類別。
但是你現在的作法完全不符合 PSR-4 標準,PSR-4 要求原始碼得要按照命名空間以及類別名稱去放置到對應的路徑與檔案名稱。也就是不管類別有多短,你都得獨立放一個檔案,而你並沒有打算照這個規定做。
要達成你的目的,Composer 的 Classmap 剛好符合需求。因為他不是按照路徑去找類別,而是直接建立類別與檔案的對應表去找到要讀取的檔案。我想你應該已經知道怎麼用,就不說明了。
結論就是你既不照 PSR-4 走,又不肯把你的檔案加入 Classmap,那當然人家找不到你的類別。