《DPT-一种PHP设计模式.docx》由会员分享,可在线阅读,更多相关《DPT-一种PHP设计模式.docx(12页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、一、DPPT介绍PHP为为什么在在主流的的应用中中总是那那么不出出色,总总是不如如.Neet/JJavaa,就是是因为在在PHP处理大大型应用用的时候候,那些些不完整整的面向向对象机机制、数数据库处处理的单单一,不不通用性性等等,影响了了PHP做大型型应用。那么,如何来来改变这这个状况况呢?当当然就是是需要引引进一些些新的设设计方法法,把PHP中不健健全的面面向对象象机制完完整起来来,进行行更好的的PHP大中型型应用的的开发。从Javva过来的MVC模式非非常流行,而且已已经有部部分已经经引伸进进了PHHP领域,设计模模式的引引进,就就是为了了更好的的控制项项目开发发。今天天我要说说一种设设计
2、模式式,类似似于MVC,它叫DPT模式。其实有有时候我我也觉得得有点象象Javva里面的DAOO(Daata Acccesss Obbjecct),不过DAO是夹在在业务逻逻辑层和和数据库库资源层层之间的的,而DPT更多的的是把业业务逻辑辑也封装装在类里里,和DAO层在相相同的内内容中。D DDataa,数据据收集层层P Phhp,PHP数据调调用层TT Teempllatee,模板板层首先先,我们们要对它它进行简简单的了了解。Dataa,就是是我们的数据层层,它不不是数据据库抽象象类,而而是通过过数据库库接口,执行一一些SQL,把数据据获取的的过程,一般把把这种操操作封装装在类里里面,就就形
3、成了了我们的的数据收收集层。Php,就是对对我们收收集的数数据进行行整理,规划,同时解解析模板板进行数数据的显显示。Tempplatte,模板板层,就就是我们们的HTMML页,里里面不包包含任何何PHP代码,只有模模板标签签的内容容,通过过它来控控制数据据在页面面中有格格式的显显示。我们们这里三三层中,每一层层都是鼓鼓励由一一个人来来开发,然后通通过PHPPDocc之类的的工具,把源代代码中的的API生成文文档,由由P层的人人进行调调用。那么么,在实实际的项项目开发中,它是怎怎么运作作的呢,我们又又如何把把这种设设计模式式引进我我们的项项目中呢呢?我们们下面将将运用一一个实际际的项目目来讲解解
4、DPT模式。阅读一一下内容容必须具具备基本本的PHPP4的面向向对象编编程、数数据库抽抽象类、模板等等知识。我们们目前为为了加速速PHP的开发发,都使使用PHP封装了了部分功功能,比比如数据据库操作作抽象类类,模板板类等等等,这些些都是为为了开发发复杂应应用而应应运而生生的。目目前比较较主流的的数据库库抽象类类有phpplibb dbb、PEAAR:DB、ADOODB等等,模板处处理类有有phpplibb teempllatee、smaartTTempplatte、Smaartyy等等。本文中中都是使用PHPP Grroupp推荐的的产品,数据口口抽象类类使用PEAAR:DB,模板板处理类类使
5、用Smaartyy,如果果对这两两个类库库不熟悉悉的读者者,请参参考文章章后面的的链接。二、项目目体系结结构下面面我们来来构建我我们基于于DPT模式的PHP应用。(以下下部分内内容参考考MVC模式、类封装装还是黑黑客代码码)文件目录录结构(只涉及及到关键键的目录录)cllasss类类库,包包含所有有的数据据收集层层temmplaate模板文文件存放放目录iinclludee常常用库,包括PEAAR、Smaartyy等类库库,同时时还有自自己定义义的基本本函数cconffig.incc.phpp基本本配置文文件,包包括数据据库配置置,其他他基本信信息配置置seccuriity.incc.phhp
6、安全全处理页页,主要要多传递递的变量量进行处处理innit.incc.phhperrrorr.phhp错错误处理理页classs目录中中存放了了我们数数据收集集层中的的内容,一般的的建议是是每个类类文件只只是针对对一个表表进行操操作,比比如cmssMesssagge.cclasss.pphp,那么么这个类类就是属属于功能能CMS里面的的,只负负责操作作Messsagge这个表表。所有有的数据据库交互互和操作作都是封封装在类类里的,在P层不允允许出现现任何直直接操作作数据库库的语句句。tempplatte目录中存放了我我们的网网页模板板,模板板中都是是使用Smaartyy标签进进行排列列的,同同
7、时,在在模板中中,都是是建议使使用JSCSS来控制制页面,模板中中只有DIV标签来来简单的的排版,这样,非常利利于网站站改版和和更换皮皮肤。inclludee目录就就是对常常用文件件的包含含,比如如PEAAR:DB类、Smaartyy类库文文件等。connfigg.innc.pphp就是基基本的配配置文件件,包括括数据库库、基本本常量等等等,seccuriity.incc.phhp是安全全处理页页,我们们这里主主要是做做一个变变量的安安全检查查,下面面内容我我们将仔仔细介绍绍。iniit.iinc.phpp是一个个初始化化操作的的页面,包括初初始化数据据库链接接,实例例化模板板处理类类等等操操
8、作,errror.phpp是错误误信息处处理页,所有的的错误信信息通过过URL编码后后转到该该页。三、项目目基本配配置代码码关键页页代码实实例:/* * connfigg.innc.pphp *配置置文件*/*数数据库配配置 */deffinee(DDB_HHOSTT, loocallhosst); /数据库库主机ddefiine(DBB_USSER, rooot); /数据库库链接用用户deefinne(DB_PASSS, ); /连接密密码deefinne(DB_NAMEE, cmms); /默认数数据库ddefiine(DBB_POORT, 33006); /数据库库端口ddefiine
9、(DBB_TYYPE, myssql); /数据库库类型ddefiine(DBB_OPPT, 11); /是否长长期链接接/*模板板信息配配置 */deffinee(TTPL_TEMMPLAATE_DIRR, ./temmplaate/); /模板目目录deefinne(TPLL_COOMPIILE_DIRR, ./temmplaate/temmplaatess_c/); /模板编编译目录deffinee(TTPL_CONNFIGGS_DDIR, ./ttempplatte/cconffigss/); /模板配配置文件件目录ddefiine(TPPL_CCACHHE_DDIR, ./temmp
10、laate/cacche/); /模板缓缓存目录录deffinee(TTPL_LIFFTTIIME, 1); /缓存时时间deefinne(TPLL_CAACHEEINGG, ttruee); /是否缓缓存deefinne(TPLL_LEEFT_DELLIMIITERR, ); /左边界界符deefinne(TPPL_RRIGHHT_DDELIIMITTER, ); /右边界界符/*网站路路径配置置 */deffinee(RROOTT_PAATH, ddirnnamee(_FILLE_); /网站所所在根目目录deefinne(URLL_PAATH, ddirnnamee($_SERRVERR
11、PHHP_SSELFF); /网站URL地址路路径deefinne(DB_PATTH, ROOOT_PATTH./inncluude/db); /PEAAR:DB目录deefinne(TPLL_PAATH, RROOTT_PAATH./iinclludee/smmartty); /SSmarrty目录/* ssecuuritty.iinc.phpp *安全过过滤文件件*/*过滤滤规则 */$arrr_ffilttratte = arrrayy(, , );/*过滤函函数 */funnctiion varr_fiiltrratee($vvar) gglobbal $arrr_ffilttratt
12、e; forreacch ($arrr_ffilttratte aas $vallue) iif (ereegi($vaar, $vaalue) rretuurn truue; reeturrn ffalsse; /*获取取不同版版本下的的GET和POSST数组 */if (phhpveersiion() 44.1.0) $geet = &$HTTTP_GGET_VARRS; $poost = &$HTTTP_POSST_VVARSS; elsse $gget = &$_GGET; $ppostt = &$_POSST;/*检查GET变量 */if (coount($geet) forreac
13、ch ($poost as $geet_vvar) iff (vvar_filltraate($geet_vvar) exiit(Commmitt geet pparaametter fallsitty); /*检查POSST变量 */if (coountt($ppostt) fforeeachh ($posst aas $posst_vvar) iff (vvar_filltraate($poost_varr) exxit(Coommiit ppostt paarammeteer ffalssityy); 其实实,以上上过滤的的方法也也不是最最好的,建议参参考我的的另两篇篇防注入入文章获获取
14、更好好的方法法,链接接参考附附录。/* eerroor.pphp*错误误处理页页面*/iff (!issset($geetmmsg) exxit(Noot ccommmit parrameeterr);echho Errror Messsagge: . $geetmmsg;eccho 返回上上一页;就是是一些错错误处理理的作用用,一般般出的GET方式传传递过来来的消息息都是经经过urllenccodee()过的字字符。/* * iinitt.innc.pphp*初始始化程序序*/reequiire_oncce(ddirnnamee(_FILLE_).connfigg.innc.pphp);rr
15、equuiree_onnce(ROOOT_PPATHH.ssecuuritty.iinc.phpp);reqquirre_ooncee(DBB_PAATH.DBB.phhp);reequiire_oncce(TTPL_PATTH.Smaartyy.cllasss.phhp);/*初始始化数据据库链接接 */$dbb = DB:coonneect(DBB_TYYPE:/DDB_UUSERRDBB_PAASS:DB_HOSST/DDB_NNAMEE, DB_OPTT);iif (DB:issErrro($db) reeturrn $dg-geetMeessaage();$tppl = &nnew
16、Smaartyy();/*初始始化模板板 */$tppl-temmplaatess_diir = TPPL_TTEMPPLATTE_DIIR;$tpll-ccomppilee_diir = TPPL_CCOMPPILEE_DIIR;$tpll-ccachhe_ddir = TPLL_CAACHEE_DIIR;$ttpl-coonfiigs = TPLL_COONFIIGS_DIRR;$ttpl-liifettimee = TPPL_LLIFTTTIMME;$tpll-ccachhingg = TPPL_CCACHHEINNG;$tpll-lleftt_deelimmiteer = TPPL_L
17、LEFTT_DEELIMMITEER;$tpll-rrighht_ddeliimitter = TTPL_RIGGHT_DELLIMITEER;基本本文件描描述完毕毕。代码码写了不不少,只只是为了了更好的的理解这这个模式式。四、框架架实际开开发说明明:我们们以下项项目代码码都是以以cms数据库库中topiic表做例例子,代代码只是是为了演演示框架架结构,没有对对代码进进行测试试,不保保证能够够正常运运行。topiic的表结结构:CREAATE TABBLE toopicc ( id innt(111) NOTT NUULL autto_iincrremeent, tittle vaarchha
18、r(2555) NNOT NULLL ddefaaultt , adddtiime innt(111) deffaullt NNULLL, aauthhor vaarchhar(50) deefauult NULLL, ttypee iint(11) deefauult NULLL, ooptiion innt(111) deffaullt NNULLL, PRIIMARRY KKEY (id), KEEY id (id);(一一)Datta层:数数据采集集层Dataa层主要要就是针针对数据据库的所所有操作作都封装装起来,然后通通过接口口的形式式提供给给Php层进行行调用,同时在在Datta层
19、里也也封装了了一些原原始的数数据库操操作(类类似于Javva中的DAO)。一般Datta层都是是类的形形式,保保存在我我们上面面的 /cclasss目录下下,一般般的准则则是一个个类文件件操作一一个数据据表,就就是说不不管具体体的业务务逻辑如如何,所所有的数数据表操操作都是是封装在在一个类类文件里里的。比比如说我我们有一一个数据据表叫做做toppic,那么么我们对对应操作作的类文文件就是是:toppic.claass.phpp。其实实这里是是可以做做扩展的的,比如如说,我我们的项项目非常常庞大,有很多多内容,比如包包括有CMS、Bloog、BBS等等,那么我我们就必必须给每每一个栏栏目分配配一
20、个数数据库,那么针针对当前前操作数数据库的的话,就就使用类类中封装装的链接接方法进进行链接接,就可可以抛弃弃我们上上面iniit.iinc.phpp中初始化化的操作作,而操操作在类类里面进进行的链链接。假设设我们目目前操作作的栏目目是CMS系统,数据库库名叫做做cms,那么么我们下下面构造造一个操操作cms数据库库里面的的toppic表的类类来。/* ccms_toppic.claass.phpp*文章章处理类类*/claass cmssToppicvaar ccmsDDBNaame; /数据库库名vvar cTaableeNamme; /当前操操作的表表名vvar cDssn; /数据链链接
21、源varr cDDebuug; /是否打打开调试试,1为是,0为否vvar cDbbPoiinteer /链接资资源vvar cfeetchhModde /获取数数据库资资料的方方式vvar cEnncodde /数据库中中数据保保存的编编码格式式,默认认是UTFF-8/*构构造函数数 */fuuncttionn cmmsToopicc() /配置信信息从connfigg.innc.pphp中设置置 $thiis-cfeetchhModde = DBB_FEETCHHMODDE_DDEFAAULTT; $thhis-cTTablleNaame = toppic; $thhis-cDDsn =
22、myssql:/. DDB_UUSERR.:. DDB_PPASSS. DBB_HOOST./. DBB_NAAME; $thiis-cEnncodde = uutf88;/*链链接数据据库 */fuuncttionn coonneectDDataabasse() if (!iis_oobjeect($cDDbPoointter) $thiis-cDbbPoiinteer = DBB:cconnnectt($tthiss-ccDsnn); iif ($thhis-cEEncoode=uutf88) $thiis-cDbbPoiinteer-queery(seet nnamees utff8);
23、 $thhis-cDDbPoointter-seetFeetchhModde($thiis-cfeetchhModde); if (DBB:iisErrrorr($tthiss-ccDbPPoinnterr) rretuurn fallse; reeturrn $thiis-cDbbPoiinteer; /*关关闭数据据库连接接 */fuuncttionn clloseeDattabaase() iif (is_objjectt($tthiss-ccDbPPoinnterr) $tthiss-ccDbPPoinnterr-ddiscconnnectt(); /*-数数据库基基本操作作 -*/*
24、插插入操作作 */fuuncttionn innserrt($arrr) iif(!is_arrray($arrr) | couunt($arrr) = 0) retturnn faalsee; iff( = $tthiss-ccTabbleNNamee) rretuurn fallse; $ddb = $tthiss-cconnnecttDattabaase(); $rres = $db-auutoEExeccutee($tthiss-ccTabbleNNamee,$aarr,DB_AUTTOQUUERYY_INNSERRT); if(DB:issErrror($rees) reeturrn
25、 $ress; ellse $innserrtIdd = ($ddb-gettOnee(sseleect LASST_IINSEERT_ID();); if($innserrtIdd0) rretuurn $innserrtIdd; eelsee retturnn trrue; /*更新操操作 */funnctiion upddatee($iid,$arrr) iif( != $id & !(iis_aarraay($arrr) reeturrn ffalsse; $ddb = $tthiss-cconnnecttDattabaase(); $rres = $db-auutoEExeccute
26、e($tthiss-ccTabbleNNamee,$aarr,DB_AUTTOQUUERYY_UPPDATTE,id = $idd); iff(DBB:iisErrrorr($rres) rretuurn fallse; elsse rretuurn truue; /*删删除操作作 */fuuncttionn deelette($id) $dbb = $tthiss-cconnnecttDattabaase(); $rres = $db-quueryy(DDELEETE FROOM .$tthiss-ccTabbleNNamee. WHEERE id = $idd); if(DB:issErr
27、ror($rees) rretuurn fallse; elsse rretuurn truue; 上面面的代码码一个很很基本的的针对一一个表操操作的类类雏形已已经描述述出来了了,包括括连接数数据库,基本的的数据库库原始操操作都有有了。你你肯定会会问,为为什么没没有把sellectt的操作作封装进进去?主主要是因因为sellectt是SQL里最复复杂的操操作,不不可能写写那么通通用的一一个方法法去操作作它,所所以好不不如不写写,自由由发挥。那么么我们需需要加上上一些基基本的功功能呢?比如读读取内容容、新增增加一篇篇文章等等操作,那么我我们还必必须在类类里面添添加一些些方法,比如我我们增加加提取
28、一一篇文章章内容、提取指指定时间间的文章章、提取取指定类类别的文文章、统统计目前前所有文文章的总总数等操操作。/* ccms_toppic.claass.phpp*文章章类增强强*/claass cmssToppic/ .上面已已经描述述的方法法省略/* *函数: ggetTTopiicCoonteentBByIdd() *功功能:获取指指定ID的文章章的内容容 *参数: $id指定要要获取的的ID * $ccolss要提提取的字字段值 *返返回:成功返返回数据据集数组组,失败败返回错错误信息息 */ffuncctioon ggetTTopiicCoonteentBByIdd($iid, $c
29、ools=*) $db = $thiis-connnecctDaatabbasee($tthiss-ccDsnn); $ssql = SELLECTT $ccolss FRROM . $thhis-cTTablleNaame . WHEERE id = $idd; $ressultt = $dbb-ggetAAll($sqql); iif (DB:issErrror($reesullt) rretuurn $reesullt-gettMesssagge(); eelsee $db-diiscoonneect(); rretuurn $reesullt; /* *函数: ggetTTopiicB
30、yySpeeciffyTiime() *功能:获取指指定时间间的文章章的列表表 *参数: $staartTTimee指定开开始时间间 * $eendTTimee结束时时间 * $cools要提取取的字段段值 *返回:成功返返回数据据集数组组,失败败返回错错误信息息 */ffuncctioon ggetTTopiicByySpeeciffyTiime($sttarttTimme=00, $enddTimme=00, $colls=*) $dbb = $thhis-coonneectDDataabasse($thiis-cDssn); $staart = ($sttarttTimme = 00)
31、? : WHHEREE adddtiime $staartTTimee; $eend = ($enndTiime = 0) ? : AAND adddtimme cTaableeNamme . .$sstarrt . .$eend; $ressultt = $dbb-ggetAAll($sqql); iif (DB:issErrror($reesullt) rretuurn $reesullt-gettMesssagge(); eelsee $db-diiscoonneect(); rretuurn $reesullt; /* *函数: ggetTTopiicByyTyppe() *功能:获取
32、指指定类别别的文章章的列表表 *参数: $typpe指指定的类类型 * $cools要提取取的字段段值 *返回:成功返返回数据据集数组组,失败败返回错错误信息息 */ffuncctioon ggetTTopiicByyTyppe($typpe, $cools=*) $db = $thiis-connnecctDaatabbasee($tthiss-ccDsnn); $ssql = SELLECTT $ccolss FRROM . $thhis-cTTablleNaame . WHEERE typpe = $typpe; $reesullt = $ddb-gettAlll($ssql); if
33、(DBB:iisErrrorr($rresuult) retturnn $rresuult-geetMeessaage(); elsse $dbb-ddiscconnnectt(); retturnn $rresuult; /* *函数: ggetTTopiicSuum() *功能:获取所所有文章章总数,如果指指定类别别,则获获取指定定类别总总数 *参数: $typpe指指定的类类型 *返回:成功返返回获取取的总数数,失败败返回错错误信息息*/fuuncttionn geetToopiccSumm($ttypee=) $db = $thiis-connnecctDaatabbasee($tth
34、iss-ccDsnn); $ttypeeStrr = ($ttypee = ) ? : WWHERRE ttypee = $ttypee; $sqll = SEELECCT ccounnt(iid) FROOM . $thiis-cTaableeNamme . .$ttypeeStrr; $reesullt = $ddb-gettOnee($ssql); if (DBB:iisErrrorr($rresuult) retturnn $rresuult-geetMeessaage(); elsse $dbb-ddiscconnnectt(); retturnn $rresuult; 上面面我们构
35、构造了一一些数据据提取类类,这应应该就是是我们Datta层的核核心了。写方法法的时候候要尽量量考虑到到扩展性性,比如如对列的的提取,比如一一个方法法适合多多种情况况,比如如排序等等等,考考虑的越越多,以以后维护护起来就就比较容容易,当当然,我我推荐的的方法是是一个方方法尽量量就做一一件事情情,如果果一个函函数要做做多个事事情,那那么就写写成多个个函数,这样便便于代码码重用和和维护性性,我个个人认为为一个方方法最用用不要超超过100行。如果果函数中中有涉及及到数据据库的操操作,一一定记得得结尾的的时候把把数据关关闭掉,不然很很容易把把服务器器资源占占用光。当然,你也可可以在PHP层去关关闭连接接
36、。比如如,你需需要很多多次调用用同一个个方法,那么这这个方法法如果反反复的连连接数据据库又关关闭数据据库,也也很浪费费资源,而且速速度慢,这个时时候就可可以把关关闭数据据库的操操作在Php层进行行关闭,你可以以先构造造好一个个方法来来进行,比如我我们上面面的 clloseeDattabaase()方法法。(二二)Php层:数数据调用用层PHP层层主要就就是把从从Datta层收集集的数据据再这一一层进行行调用。因为我我们基本本的原则则就是把把所有跟跟数据库库的操作作都封装装在Datta层里,在其他他层都不不涉及到到任何的的直接对对数据库库的操作作,这样样能够进进行良好好的封装装,这样样有点类类似
37、于 JSSP和Javvabeean,Javvabeean的类负负责和数数据库交交互,JSP负责调调用Javvabeean来输出出数据。我们这这里的PHP层就相相当于JSP层,前前面的Datta层就相相当于Javvabeean层,这这样玻璃璃他们之之间的耦耦合度,能够方方便程序序日后的的维护。我们们这里的的PHP层主要要就是复复杂从数数据库种种提取数数据,完完成一些些简单的的逻辑,然后把把数据输输出到Temmplaate(模板板层)。现在我我们利用用示例代代码来看看看PHP层是如如何调用用Datta层的数数据的。/* ttopiic_llistt.phhp*文章列列表程序序*/*包含含基本文文件
38、 */reqquirre_ooncee(iinitt.innc.pphp);rrequuiree_onnce(cllasss/cmms_ttopiic.cclasss.pphp);/实例例化Datta层对象象$toopicc = neww cmmsToopicc();/获取文文章类型型变量$toppicTTypee = inttvall(geet(typpe);/从Datta层中把把数据提提取过来来$toopiccLisst = geetToopiccByTTypee($ttopiicTyype);/给模模板变量量赋值后后输出页页$tppl-asssignn(ttopiic, $ttopiic
39、Liist);$ttpl-asssiggn(toppic.htmml);代码码是不是是很简单单?就是是把数据据获取过过来,然然后解析析到模板板层中去去处理,所以这这样如果果以后出出现问题题改起来来比较容容易,比比如是数数据获取取的问题题,那么么直接改改上面的的类文件件就行,如果是是模板显显示的问问题,那那么直接接修改模模板层中中的对应应的模板板页就可可以,非非常便于于维护。(三三)Temmplaate层:模模板层这个个模板层层就是我我们常说说的网页页了,不不过这里里就是包包含了一一些Smaartyy的模板板变量和和HTMML混和,模模板页处处理的时时候就对对页面中中的模板板变量进进行替换换,最
40、后后我们看看到的结结果就是是模板页页和PHP层中的的程序输输出混和和的结果果。一般模板板页设计计的时候候,最好好遵循Web标准,就是说说尽量在在页面中中不使用用表格等等htmml标签来来控制页页面,而而是使用用div层来存存放数据据,使用用css样式表表来控制制页面布布局,这这样对包包括JavvaSccrippt脚本的的编写,以后页页面的改改版等等等非常有有好处。而且如如果要还还模板也也很简单单,只需需要把css文件替替换就可可以达到到效果。当然,如果对对web标准不不了解,那么建建议去阅阅读一下下网站站重构这本书书。我们们下面就就简单的的描述一一下Temmplaate(模板板层)的的代码是是
41、如何的的。*加载载头部文文件 *inncluude fille=heaaderr.httml*模板板主体 *左左边导航航条 *文章列列表seectiion namme=ttopiicLiist looop=$toppic标题:$toopicctoopiccLisst.tittle|esccapee:hhtmll|ttrunncatte:330:.:ttruee |时间:$ttopiicttopiicLiist.adddtiime|datte_fformmat:%YY年%m月%d日 |作者:$ttopiicttopiicLiist.auuthoor|eescaape:httmlsecctioonellse暂时没没有任何何文章/ssecttionn*加载载底部文文件 *inncluude fille=fooot.hhtmll模板板页中大大致可能能有一些些JavvaSccrippt程序,或者有有样式文文件,一一般使用用样式文文件来控控制页面面的布局局和显示示效果。我们这这里没有有详细的的描述,在实际际项目中中可以由由网页制制作人员员去负责责。五、使用用DPT模式的的项目规规划一般般在所有有的软件件项目或或者是网网站项目目中,要要保证一一个项目目能够顺顺利完整整的完成成,那么么便需要要技术主主管或者者架构师师良好的的设计和和管理。一般所所有项目目中人是是最