目前网络上充斥着大量的陈旧信息,让PHP新手误入歧途,传播着错误的实践和糟糕的代码,这必须得到纠正。PHP之道网站的目标就是搜集PHP最佳实践、编码规范和网络上的权威学习指南,给PHP学习者提供一个易于阅读,快速查找的入口。
PHP之道已经翻译成多种语言:
PHP没有规范化的使用方式,本网站只是展示业界的最佳实践、可用的选项和有用的信息,目的是帮助PHP新手,并对以往的经验进行反思。
PHP之道有多个banner宣传图片可以放在你的站点上显示,让更多开发者知道这个网站,找到权威的学习资料!
有了它,你可以不用安装和配置功能齐全的Web服务器,就可以开始学习PHP(要求PHP5.4+版本)。要启动内置Web服务器,需要从你的命令行终端进入项目的Web根目录,执行下面的命令:
>php-Slocalhost:8000Mac安装OSX系统会预装PHP,只是版本比最新稳定版低一点。目前Lion下是PHP5.3.6,MountainLion下是5.3.10,Mavericks下是5.4.17.
如果你想获取一些Vagrant的使用帮助的话,可以参考下面的三个服务:
PHP社区百花齐放,拥有大量的函数库、框架和组件。PHP开发者通常会在自己的项目中使用若干个外部库,因而PHP代码遵循或尽量接近同一个代码风格就非常重要,可以让开发者方便地把多个代码库集成在自己的项目中。
通常情况下,你的PHP代码应该遵循其中一项或多项标准,从而其他开发者可以方便地阅读和使用你的代码。这些标准都是在前一个标准上附加新的规则,所以使用PSR-1就同时要求遵循PSR-0,但可以不遵循PSR-2。
变量名和代码结构建议使用英文符号编写,注释则可以使用各种语言,没有限制。
PHP是一个灵活的动态语言,支持多种编程范式。这些年来一直在不断的进化,重要的里程碑包括PHP5.0(2004)增加完善的面向对象模型、PHP5.3(2009)增加匿名函数和命名空间和PHP5.4(2012)增加traits.
PHP具有完整的面向对象编程特性,如类、抽象类、接口、继承、构造函数、克隆和异常等。
PHP支持第一类函数(first-classfunction),即函数可以赋值给变量,包括用户自定义的函数和内置函数,然后动态调用它。函数可以作为参数传递给其他函数(即高阶函数),也可以作为函数返回值返回。
PHP支持函数递归调用,即函数自己调用自己,不过在实际的PHP代码中,我们更喜欢用迭代来代替递归。
2009年发布的PHP5.3开始引入支持闭包的匿名函数。
PHP5.4支持把闭包绑定到对象作用域,并改善其可调用性,从而可以在大部分场景中使用匿名函数替代普通函数。
PHP通过反射API和魔术方法机制,支持多种方式的元编程。开发者通过魔术方法,如__get(),__set(),__clone(),__toString(),__invoke()等,可以改变类的行为。Ruby开发者经常说PHP没有method_missing方法,实际上通过__call()和__callStatic()就可以完成同样的功能。
如前所述,PHP社区的众多开发者已经开发了大量的代码。这意味着一个函数库中的PHP代码可能使用了另外一个库中相同的类名,如果它们共享一个命名空间,则会产生冲突导致异常。
命名空间解决了这个问题。如PHP手册里描述的那样,命名空间类似于操作系统中的目录,两个同名文件可以共存于不同的目录。同理,同名的PHP类可以在不同的PHP命名空间下共存,就这么简单。
因而把代码放在自己的命名空间下就显得非常必要,这样其他人就可以放心的使用这些代码,而无需担心与其他函数库的命名冲突。
标准PHP库(SPL)和PHP一起发布,提供了一组类和接口,包括了常用的数据结构如栈,队列和堆等,以及遍历这些数据结构的迭代器,或者你还可以自己实现SPL接口。
PHP的主要目的是开发Web应用,不过它的命令行脚本接口(CLI)也非常有用。PHP命令行编程可以帮你完成自动化的任务,如测试,部署和应用管理。
CLIPHP编程非常强大,可以直接调用你自己的app代码而无需创建Web图像界面,需要注意的是不要把CLIPHP脚本放在公开的web目录下!
在命令行下运行PHP:
接下来写一个简单的”Hello,$name”CLI程序,先创建名为hello.php的脚本:
运行上面的脚本,在命令行输入:
>phphello.phpUsage:phphello.php[name]>phphello.phpworldHello,worldXDebug调试器是软件开发过程中非常重要的一个工具,通过它,可以跟踪代码的执行过程,查看堆栈信息。XDebug是一个PHP调试器,可以集成在常见的IDE中,提供设置断点、查看堆栈信息等功能,还可以和PHPUnit、KCacheGrind等工具配合,执行代码覆盖率测试和性能调优。
如果你现在还没有使用调试器,仅仅依靠var_dump/print_r调试的话,XDebug就是你的最佳选择。
通常,你需要修改Apache虚拟主机或者.htaccess配置文件,增加:
php_valuexdebug.remote_host=192.168..php_valuexdebug.remote_port=9000“remotehost”和”remoteport”对应本机IDE的监听地址和端口,然后设置IDE为”等待连接”模式,打开URL:
图形化调试器使得单步调试、查看变量和现场运行代码变得异常简单,很多IDE都自带或者通过第三方插件支持xdebug的调试,如Mac平台下的开源软件MacGDBp。
如今有大量的PHP函数库、框架和组件可供选择,一个项目中可能会使用其中的若干——这就是项目的依赖。到目前为止,PHP还没有有效的项目依赖管理方案。即使你手工的管理它们,你还不得不处理它们的自动加载问题。
目前主要有两个PHP包管理系统:Composer和PEAR,哪个适合你呢?答案是两个都需要。
通常情况下,Composer包只在你项目中明确指定时才可用,而PEAR包在所有的PHP项目中可用。尽管PEAR听起来似乎更简单,但是根据每个项目制定方案可能更合适。
Composer是一个出色的PHP依赖管理器,把项目的依赖列在composer.json文件中,然后通过一些简单的命令,Composer就会自动的帮你下载这些依赖,并配置好自动加载路径。
Composer可以安装在本地(在当前工作目录,不推荐这种方式),也可以安装在系统中(如/usr/local/bin)。假设你要在本地安装,在项目的根目录执行:
手动安装composer有点麻烦,不过很多开发者可能更喜欢这种安装方式。使用交互式安装程序,它会检查你安装的PHP:
而手动安装则需要你自己做这些事情,你必须自己权衡利弊,以决定是否手动安装。下面是手动获取Composer的方法:
这样文档中描述的运行Composer的命令phpcomposer.pharinstall,就可以用如下命令替代:
composerinstall下面默认你已经在PATH路径下安装Composer。
composerrequiretwig/twig:~1.8或者通过composerinit命令也可以一步步地引导你创建项目所需的composer.json文件。无论使用哪种方式创建了composer.json文件后,就可以通过Composer下载和安装项目依赖到目录vendors/:
composerinstall最后在应用的PHP入口文件添加下面代码,告诉PHP使用Composer自动加载器加载项目的依赖库:
Composercreatesafilecalledcomposer.lockwhichstorestheexactversionofeachpackageitdownloadedwhenyoufirstranphpcomposer.pharinstall.Ifyoushareyourprojectwithothercodersandthecomposer.lockfileispartofyourdistribution,whentheyrunphpcomposer.pharinstallthey’llgetthesameversionsasyou.Toupdateyourdependencies,runphpcomposer.pharupdate.
Thisismostusefulwhenyoudefineyourversionrequirementsflexibly.Forinstanceaversionrequirementof~1.8means“anythingnewerthan1.8.0,butlessthan2.0.x-dev”.Youcanalsousethe*wildcardasin1.8.*.NowComposer’sphpcomposer.pharupdatecommandwillupgradeallyourdependenciestothenewestversionthatfitstherestrictionsyoudefine.
PEARrequireseachpackagetohaveaspecificstructure,whichmeansthattheauthorofthepackagemustprepareitforusagewithPEAR.UsingaprojectwhichwasnotpreparedtoworkwithPEARisnotpossible.
PEARinstallspackagesglobally,whichmeansafterinstallingthemoncetheyareavailabletoallprojectsonthatserver.Thiscanbegoodifmanyprojectsrelyonthesamepackagewiththesameversionbutmightleadtoproblemsifversionconflictsbetweentwoprojectsarise.
IfyouareusingLinux,youcanalsohavealookatyourdistributionpackagemanager.DebianandUbuntu,forexample,haveanaptphp-pearpackage.
pear-channel/Package
The“pear”prefixishardcodedtoavoidanyconflicts,asapearchannelcouldbethesameasanotherpackagesvendornameforexample,thenthechannelshortname(orfullURL)canbeusedtoreferencewhichchannelthepackageisin.
WhenthiscodeisinstalleditwillbeavailableinyourvendordirectoryandautomaticallyavailablethroughtheComposerautoloader:
vendor/pear-pear2.php.net/PEAR2_HTTP_Request/pear2/HTTP/Request.php
TousethisPEARpackagesimplyreferenceitlikeso:
PHP是一个伟大的语言,可以让各个层次的程序员都能够快速高效地完成编码任务。虽然如此,我们还是经常会因为临时救急或者坏习惯而忽视了PHP的基础。为了解决这个问题,这部分专门给开发者回顾一下PHP的基础编码实践。
如果你的项目使用了框架,那么在代码和项目结构上,都会遵循框架的约束,自然也就继承了框架中的各种模式,这时你所需要考虑的是让上层代码也能够遵循最合适的模式。反之,如果没有使用框架,那么就需要你自己选择适用于当前项目类型和规模的最佳模式了。 Dependencyinjectionisasoftwaredesignpatternthatallowstheremovalofhard-codeddependenciesandmakesitpossibletochangethem,whetheratrun-timeorcompile-time. Thisquotemakestheconceptsoundmuchmorecomplicatedthanitactuallyis.DependencyInjectionisprovidingacomponentwithit’sdependencieseitherthroughconstructorinjection,methodcallsorthesettingofproperties.Itisthatsimple. Wecandemonstratetheconceptwithasimple,yetnaiveexample. HerewehaveaDatabaseclassthatrequiresanadaptertospeaktothedatabase.Weinstantiatetheadapterintheconstructorandcreateaharddependency.ThismakestestingdifficultandmeanstheDatabaseclassisverytightlycoupledtotheadapter. IfyouhaveeverreadaboutDependencyInjectionthenyouhaveprobablyseentheterms“InversionofControl”or“DependencyInversionPrinciple”.ThesearethecomplexproblemsthatDependencyInjectionsolves. InversionofControlisasitsays,“invertingthecontrol”ofasystembykeepingorganisationalcontrolentirelyseparatefromourobjects.IntermsofDependencyInjection,thismeanslooseningourdependenciesbycontrollingandinstantiatingthemelsewhereinthesystem. Foryears,PHPframeworkshavebeenachievingInversionofControl,however,thequestionbecame,whichpartofcontrolareyouinverting,andwheretoForexample,MVCframeworkswouldgenerallyprovideasuperobjectorbasecontrollerthatothercontrollersmustextendtogainaccesstoitsdependencies.ThisisInversionofControl,however,insteadoflooseningdependencies,thismethodsimplymovedthem. DependencyInjectionallowsustomoreelegantlysolvethisproblembyonlyinjectingthedependenciesweneed,whenweneedthem,withouttheneedforanyhardcodeddependenciesatall. DependencyInversionPrincipleisthe“D”intheS.O.L.I.Dsetofobjectorienteddesignprinciplesthatstatesoneshould“DependonAbstractions.Donotdependonconcretions.”.Putsimply,thismeansourdependenciesshouldbeinterfaces/contractsorabstractclassesratherthanconcreteimplementations.Wecaneasilyrefactortheaboveexampletofollowthisprinciple. Considerthatyouareworkinginateamandtheadapterisbeingworkedonbyacolleague.Inourfirstexample,wewouldhavetowaitforsaidcolleaguetofinishtheadapterbeforewecouldproperlymockitforourunittests.Nowthatthedependencyisaninterface/contractwecanhappilymockthatinterfaceknowingthatourcolleaguewillbuildtheadapterbasedonthatcontract. Anevenbiggerbenefittothismethodisthatourcodeisnowmuchmorescalable.Ifayeardownthelinewedecidethatwewanttomigratetoadifferenttypeofdatabase,wecanwriteanadapterthatimplementstheoriginalinterfaceandinjectthatinstead,nomorerefactoringwouldberequiredaswecanensurethattheadapterfollowsthecontractsetbytheinterface. ThefirstthingyoushouldunderstandaboutDependencyInjectionContainersisthattheyarenotthesamethingasDependencyInjection.AcontainerisaconvenienceutilitythathelpsusimplementDependencyInjection,however,theycanbeandoftenaremisusedtoimplementananti-pattern,ServiceLocation.InjectingaDIcontainerasaServiceLocatorintoyourclassesarguablycreatesaharderdependencyonthecontainerthanthedependencyyouarereplacing.Italsomakesyourcodemuchlesstransparentandultimatelyhardertotest. MostmodernframeworkshavetheirownDependencyInjectionContainerthatallowsyoutowireyourdependenciestogetherthroughconfiguration.Whatthismeansinpracticeisthatyoucanwriteapplicationcodethatisascleanandde-coupledastheframeworkitisbuilton. 如果应用只是使用一个数据库的话,原生驱动就工作的非常好,否则使用MySQL的同时,还需要使用MSSQL或Oracle数据库的话,那么就没有办法只使用一个原生驱动了,只能分别学习各个数据库驱动的API,这非常令人生厌。 PDO是数据库连接抽象库,从PHP5.1.0开始提供,提供多种数据库的统一的操作接口。PDO不会转化你的SQL查询或者模拟缺失特性;它只是提供统一的API去连接不同的数据库而已。 更重要的是,PDO允许你绑定SQL查询语句中的变量,而无需担心SQL注入问题,这主要通过PDOstatements和变量绑定来实现。 假设PHP脚本接收一个数字ID作为查询参数,从数据库取回一条记录。下面是一种错误的做法: 另外一个要注意的问题是,如果数据库连接没有隐式地关闭,那么数据库连接数可能会超过数据库服务器的限制而连接失败,这种错误在其他编程语言中比较常见。PDO对象在销毁的时候会隐式的关闭数据库连接,只要你把指向它的引用全部删除即可,如设置为NULL。如果没有,PHP也会在脚本结束时关闭所有非持久化的数据库连接。 很多框架都提供了自己的数据库抽象层,有的是基于PDO,有的不是。它们通过PHP方法来包装实际的查询,能够模拟出只存在于某些数据库系统的特性,给你一个真正的数据库抽象层。这么做会带来一些性能的损失,但是在一个需要支持MySQL、PostgreSQL和SQLite的应用中,这个损失相对于由此带来的代码一致性而言是可以接受的。 PHPhasseverallevelsoferrorseverity.Thethreemostcommontypesofmessagesareerrors,noticesandwarnings.Thesehavedifferentlevelsofseverity;E_ERROR,E_NOTICE,andE_WARNING.Errorsarefatalrun-timeerrorsandareusuallycausedbyfaultsinyourcodeandneedtobefixedasthey’llcausePHPtostopexecuting.Warningsarenon-fatalerrors,executionofthescriptwillnotbehalted.Noticesareadvisorymessagescausedbycodethatmayormaynotcauseproblemsduringtheexecutionofthescript,executionisnothalted. AnothertypeoferrormessagereportedatcompiletimeistheE_STRICTmessage,thesemessagesareusedtosuggestchangestoyourcodetohelpensurebestinteroperabilityandforwardcompatibilityforyourcode. 异常是大部分流行语言的标准特性,但是PHP开发者却不太重视。其他语言如Ruby极度倚赖异常,在任何错误发生的时候,如HTTP请求失败、DB查询错误,甚至图片资源未找到,都会抛出一个异常,以及时提示那里发生了一个错误。 PHP则对此很宽松,如调用file_get_contents()失败,只是返回FALSE并提示一个warning信息而已。很多老的PHP框架,如CodeIgniter会返回false,然后在自己的日志里记录一个消息,开发者需要使用如$this->upload->get_error()的方式来查看发生了什么错误。这么做需要你自己检查是否有错误,并需要根据不同类调用不同的方法来获取错误消息,而不能让错误明显的显示出来。 这种做法的另外一个弊端是当类自动在屏幕打印一个错误,然后退出进程,阻止了其他开发者动态处理该错误的机会。而异常则是让开发者知道发生了错误,并让他们选择如何处理: 如使用__call()魔术方法,对不存在的方法调用抛出一个thrownewBadFunctionCallException;,既避免了抛出含义模糊的Exception异常,也省去了自定义异常类的麻烦。 EventuallyeveryonebuildsaPHPapplicationthatreliesonuserlogin.Usernamesandpasswordsarestoredinadatabaseandlaterusedtoauthenticateusersuponlogin. Hashingpasswordswithpassword_hash InPHP5.5password_hashwasintroduced.AtthistimeitisusingBCrypt,thestrongestalgorithmcurrentlysupportedbyPHP.Itwillbeupdatedinthefuturetosupportmorealgorithmsasneededthough.Thepassword_compatlibrarywascreatedtoprovideforwardcompatibilityforPHP>=5.3.7. Belowwehashastring,andthencheckthehashagainstanewstring.Becauseourtwosourcestringsaredifferent(‘secret-password’vs.‘bad-password’)thisloginwillfail. 当外部数据被存储合并之后,下次读取时,它们仍然算是外部输入,每次在代码中处理的时候,需要问自己是否已经正确过滤,是否可以信任它们。 数据需要根据不同用处,进行不同的_过滤_,如果把未经过滤的数据输出到HTML页面,它可以在你的网站里执行HTML和JavaScript!即通常说的跨站脚本攻击(XSS)。避免XSS的一个策略就是使用strip_tags函数过滤外部输入的所有HTML标签,或者使用htmlentities/htmlspecialchars转义其中的HTML实体。 另外一个例子是传给命令行命令的选项,这可能非常危险(通常不是一个好主意),不过你可以用内置的escapeshellarg函数过滤命令行的参数。 在创建应用的配置文件时,请遵循下面的业界最佳实践: 提示:从PHP5.4.0开始,register_globals配置已经删除,不再生效。保留这个配置,只是提示依赖该配置的应用进行升级。 错误日志可以帮助追查应用的Bug,但是也会暴露应用的结构信息而产生安全问题,为此,需要在开发环境和线上环境设置不同的配置,防止敏感信息的泄漏。 要在开发环境显示错误提示,需要在php.ini中配置以下配置项: -1表示显示各种错误,包括将来增加的新错误类型,和PHP5.4中的E_ALL行为相同。 E_STRICT错误级别在5.3.0版本引入,不在E_ALL中,不过5.4.0版本开始,E_ALL包含E_STRICT级别的错误。所以在5.3版本中,要显示所有错误,需要把error_reporting设置为-1或者E_ALL|E_STRICT。 各PHP版本显示所有错误的配置 要在线上环境隐藏错误提示,需要在php.ini中配置以下配置项: 为PHP代码编写自动化测试被认为是一个最佳实践,可以帮助你构建出高质量的应用。自动化测试可以帮助你确认没有因为重构或添加新功能而破坏原有功能,所以应该重视自动化测试。 PHP有多种类型的测试工具和框架可以使用,具体方法各有区别——但是它们的目标都是避免手工测试,满足大型QA组织的需求,保证最新的更改没有破坏已有功能。 目前对应用有多种类型的测试: 单元测试是从编写开始,贯穿于整个开发周期的一种用于保证函数、类和方法的行为与预期一致的编程方法。通过检查各个函数和方法的输入和输出值,你可以保证它们内部逻辑已经正确执行;通过依赖注入、编写mock类和stubs,你可以验证依赖是否已经正确处理,提高测试覆盖率。 在编写一个类或函数的时候,应该为它的每一个行为创建一个单元测试,至少你要保证它收到错误参数时能够触发错误,而参数正确时能正常工作。这可以帮你在后面修改类或函数的时候,确认已有功能仍然正常工作。PHP中var_dump()的功能与此类似,但是它是无法用于创建应用的。 单元测试的另外一个用武之地是在给开源项目贡献代码时,如果你编写一个测试,证明代码存在bug,然后修复代码,让测试通过,这样该补丁被接受的概率要高很多。如果你的项目接受人家的补丁,你应该把单元测试作为项目的一项要求。 集成测试(也称集成与测试,缩写为I&T)是把各个独立模块集成在一起,作为一个整体进行测试的软件测试阶段,它处于单元测试和验收测试之间。集成测试把已经做过单元测试的模块集成在一块,然后运行集成测试用例,最终输出一个可以进行系统测试的系统。 很多单元测试工具同时也可以用于集成测试,并且原理也是相通的。 有时也称为验收测试,使用工具创建自动化的测试用例,然后在真实的系统上运行,这一点与单元测试验证单个模块的正确性和集成测试验证模块间交互的正确性是有区别的,这些工具通常使用真实的数据集来模拟真实用户的使用行为来验证系统的正确性。 除了测试驱动和行为驱动开发框架,还有大量的通用框架和函数库,可以在各种开发方法下使用。 部署PHP应用到线上Web服务器的方式有很多种。 PaaS提供运行PHPWeb应用所需的系统和网络环境,对PHP应用和框架只需要做少量的配置即可。 如果你愿意或想学习系统管理,那么虚拟或独立主机可以让你完全控制自己的运行环境。 PHP非常流行,很少有服务器没有安装PHP的,因而有很多共享主机,不过需要注意服务器上的PHP是否是最新稳定版本。共享主机允许多个开发者把自己的网站部署在上面,这样的好处是费用非常便宜,坏处是你不知道将和哪些网站共享主机,因此需要仔细考虑机器负载和安全问题。如果项目预算允许的话,避免使用共享主机是上策。 Amongthetasksyoumightwanttoautomateare: Buildtoolscanbedescribedasacollectionofscriptsthathandlecommontasksofsoftwaredeployment.Thebuildtoolisnotapartofyoursoftware,itactsonyoursoftwarefrom‘outside’. Therearemanyopensourcetoolsavailabletohelpyouwithbuildautomation,somearewritteninPHPothersaren’t.Thisshouldn’tholdyoubackfromusingthem,ifthey’rebettersuitedforthespecificjob.Hereareafewexamples: ChefresourcesforPHPdevelopers: Furtherreading: ContinuousIntegrationisasoftwaredevelopmentpracticewheremembersofateamintegratetheirworkfrequently,usuallyeachpersonintegratesatleastdaily—leadingtomultipleintegrationsperday.Manyteamsfindthatthisapproachleadstosignificantlyreducedintegrationproblemsandallowsateamtodevelopcohesivesoftwaremorerapidly. –MartinFowler PHP自身效率很高,但是执行创建远程连接、加载文件等操作时容易出现瓶颈,幸运的是,我们有很多工具来加速这部分操作,或减少这些耗时操作的执行次数。 在一个PHP文件被执行时,它先被编译为字节码(也称opcode),然后这些字节码被执行。如果文件没有修改,那么字节码也会保持不变,这意味着编译这一步白白浪费了CPU资源。 这就是引入字节码缓存的原因,通过把字节码保存在内存中来消除冗余的编译,重用它们完成后续的调用。配置字节码缓存非常简单,而且可以极大地提高应用的执行效率,没有理由不使用字节码缓存。 很多时候,在代码中缓存对象可以带来很大的收益,例如获取代价很大的数据和查询结果很少变化的数据库调用。我们可以使用对象缓存系统缓存这些数据,大大加快后续的同类访问请求。如果你在取得这些数据之后,把它们缓存在系统中,在后续对这些数据的请求中,就可以直接使用缓存中的对象,这么做可以很大的提示系统性能,减少服务器的负载。 很多流行的字节码缓存方案也允许你缓存自定义数据,因此我们更应该充分利用对象缓存功能。APCu、XCache和WinCache都提供API,让你把数据缓存在他们的内存cache中。 使用最多的内存对象缓存系统是APCu和memcached,APCu是很好的一个对象缓存方案,它提供了简单的API来让你把对象存储在内存中,而且配置和使用都非常容易,它的一个缺点是只能在本机使用。Memcached则是另外一种方式,它是一个单独的服务,可以通过网络访问,这意味着可以在一个地方写入数据,然后在不同的系统中访问这份数据。 NotethatwhenrunningPHPasa(Fast-)CGIapplicationinsideyourwebserver,everyPHPprocesswillhaveitsowncache,i.e.APCudataisnotsharedbetweenyourworkerprocesses.Inthesecases,youmightwanttoconsiderusingmemcachedinstead,asit’snottiedtothePHPprocesses. 在单机性能上,APCu通常比Memcached更高,如果你不需要多台服务器或者其他Memcached的高级功能,APCu可能是你的最佳选择。 APCu的示例: 学习更多对象缓存系统: 大量的PHP开发者使用框架,而不是重复发明轮子来创建自己的Web应用。框架抽象出底层通用的业务逻辑,给使用者了提供简单易用的接口。 不是所有的项目都需要框架,有时候原生的PHP就能满足需求,但是需要框架的时候,有三种类型的框架可供选择: 微框架仅是一个包装器(Wrapper),尽量快地把HTTP请求路由到回调函数、控制器或方法上,有些框架也会提供一些函数库,如基本的数据库操作。微框架主要用于构建远程HTTP服务。 全能框架则是在微框架的功能之上提供了更多的功能特性,如ORM,验证组件等。 组件框架则是一组独立功能库的集合,多个基于组件的框架集合在一起,甚至可以用作微框架或者全能框架。 如前所述,组件是另外一种创建、实现和发布开源代码的方式,当前社区存在很多组件库,最主要的两个: ThePHPcommunityalsohostslargerregionalandnationalconferencesinmanycountriesaroundtheworld.Well-knownmembersofthePHPcommunityusuallyspeakattheselargerevents,soit’sagreatopportunitytolearndirectlyfromindustryleaders.