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