就是一個開源系統(tǒng)
系統(tǒng)某些功能函數(shù)文件路徑為:/cms/Model/Member.php
<?php
namespace Phpcmf\Model;
class Member extends \Phpcmf\Model {
public function author($uid) {
if (!$uid) {
return dr_lang('游客');
}
return $this->username($uid);
}
}
此文件是系統(tǒng)文件 - 不要修改當cms核心更新時會被覆蓋
二次開發(fā)時,支持復制出去修改 增加 功能函數(shù)方法,操作方法:
1、新建文件:/My/Member.php
2、新寫方法體:
<?php
namespace My\Model;
// 重寫類
class Member extends \Phpcmf\Model\Member{
//開始寫你的方法
public function login_TTT($uid) {
return $uid.'登錄成功';
}
}
就是這樣 當我調(diào)用:Phpcmf\Model\Member 時 author 和 login_TTT 都可以使用。
請問一下這樣是如何實現(xiàn)的???我試圖用webman 也這樣實現(xiàn)但是沒搞懂我應該怎么寫才會讓我自己新建的文件被加載進去。
看不明白,B extends A之后,A可以使用B新加的方法?
你說的是My\Model\Member可以使用author和login_TTT,還是Phpcmf\Model\Member?
可以調(diào)用A B 2個文件中的所有方法 這個意思
你這個文檔,說的不就是繼承么???我怎么感覺你理解錯他的意思了?
就類似Workerman的Request類你想新增方法,就繼承這個Request類后新增方法就好,Workerman更新也不會影響你使用的方式
我的意思:
比如目錄:/plugin/user/app/api/
下面的某個文件(testa.php )
然后我在根目錄下新建一個目錄+文件:ceshi\testb.php:
class Test extends \plugin\user\app\api\Testa {
}
在寫項目調(diào)用時,我在controller下面比如新建個文件Abccontroller :
use plugin\user\app\api\testa
就可以調(diào)用到
\plugin\user\app\api\testa.php 和 ceshi\testb.php 這2個文件里面的所有方法
好像是通過Service 的
最終調(diào)用方法為:
\Phpcmf\Service::M('member')->login_TTT(1);
請教一下webman 如何想實現(xiàn)如此,有沒有教程 案例,我沒搞懂這是怎么實現(xiàn)的!我寫了繼承方法但是壓根沒作用
看北月的回答,看了下他那個代碼,一樣的道理
// dayrui/Fcms/Core/Service.php 390行開始
if (!isset(static::$instances[$_cname]) or !is_object(static::$instances[$_cname])) {
require_once $classFile;
// 自定義繼承類
if ($extendFile && is_file($extendFile)) {
if ($namespace && is_file($appFile)) {
require_once $appFile;
$newClassName = '\\Phpcmf\\Model\\'.ucfirst($namespace).'\\'.$className;
} else {
require $extendFile;
$newClassName = '\\My\\Model\\'.$className;
}
} else {
$newClassName = '\\Phpcmf\\Model\\'.$className;
// 多個應用引用同一個類名稱時的區(qū)別
if ($namespace) {
$newClassName2 = '\\Phpcmf\\Model\\'.ucfirst($namespace).'\\'.$className;
if (class_exists($newClassName2)) {
static::$instances[$_cname] = new $newClassName2();
return static::$instances[$_cname];
}
}
}
static::$instances[$_cname] = new $newClassName();
}
\Phpcmf\Service::M($name = '', $namespace = '')
不帶命名空間就掃描My目錄下對應的Model,帶了就掃碼指定命名空間的Model
結(jié)論:就是繼承,明顯是不是什么父類調(diào)用子類的方法,跟北月說的方式大差不差
webman 的話 我是應該把它寫到:app/functions.php 還是每個pulgin 下面server 定義一個,我就是沒想到好方法,我想每個plugin下的應用核心由我開發(fā)更新,同時允許用戶在根目錄:diy/同plugin應用名/ 下面新建文件自定義開發(fā),這樣我負責升級plugin 應用下面核心,這樣當我更新時直接覆蓋,從而不會影響用戶自己二開的代碼
規(guī)定重寫后的文件必須放到指定目錄,比如 ext/model
在 composer.json
新增一個 psr-4
的自動加載項,"ext\\": "ext"
,執(zhí)行 composer dump-autoload
規(guī)定不要在 controller
中單獨使用 model
類,可以在 controller
基類中寫一個方法,或者在助手函數(shù)中實現(xiàn)也行,哪里實現(xiàn)不重要,比如就叫:getModelInstance
function getModelInstance(string $name, string $namespace = 'app\\model')
{
// 判斷 $name、$namespace是否為空,類是否存在等的一系列操作
// ....
// 首字母大小寫啥的,你喜歡怎么處理就怎么處理,但是必須規(guī)范化,讓用戶在二次開發(fā)的時候必須遵守
// 傳入的時候也是統(tǒng)一的,比如 $name = 'member',$namespace = 'app\model'
// 你可以這里進行更多的限制,比如說哪些命名空間下的 model 是可以重寫的
// 拼接 model 類名
$coreModelClassName = $namespace . '\\' . ucfirst($name);
$extModelClassName = 'ext\\model\\' . ucfirst($name);
if (class_exists($extModelClassName)) {
return new $extModelClassName;
} else {
return new $coreModelClassName;
}
}
在 controller
中調(diào)用傳入 model
名,比如你的 CMS
內(nèi)核有一個會員相關(guān)的 model
,那么調(diào)用的時候是這樣子的:
<?php
namespace app\controller;
use support\Request;
use support\Response;
class IndexController
{
public function index(Request $request): Response
{
// 這樣子寫編輯器沒有代碼提示,體驗極差
$user = getModelInstance('user');
echo $user->getUserId(),PHP_EOL;
echo $user->getUserName(),PHP_EOL;
return json(['code' => 0, 'msg' => 'ok']);
}
}
PS: 其實說到底就是優(yōu)先使用 ext/model
下的 model
類,更進一步的做法可以封裝 logic
或 service
層,思路就是這樣子,其它的可以自己擴展。