Modern PHP讀書筆記1
Jun 13, 2016 pm 12:29 PM
Modern PHP讀書筆記一
關(guān)于PHP,大家的誤解比較多,但其實(shí)現(xiàn)代PHP是一門無論開發(fā)效率還是執(zhí)行效率都相當(dāng)高的編程語言。關(guān)于現(xiàn)代PHP的各方面特性,大家可以參考<modern php></modern>
作者之前寫的 PHP the right way,中文翻譯:PHP之道。同時(shí),作者也是比較流行的PHP框架 – Slim 的開發(fā)者。所以這本書非常值得已讀,甚至你只需要懂一些OOP的概念即可,并不需要你懂PHP開發(fā)。
- Part 1 Language Feature
- Features
- Namespaces
- Helpful Tips
- Code to an interface
- Trait
- Generators
- Closures
- Zend Opcache
- Built-in HTTP server
- Namespaces
- Features
- Part 2 Good Pratices
- Standards
- PHP-FIG
- PSR
- PSR-1 Basic Coding standard
- PSR-2 Strict Code Style
- PSR-3 Logger Interface
- PSR-4 Autoloaders
- Components
- Components
- Composer
- Semantic Versioning
- Create PHP Components
- Standards
Part 1. Language Feature
Features
Namespaces
PHP命名空間使用 “\” 字符來分割sumnamespaces。與操作系統(tǒng)的物理文件系統(tǒng)不同,PHP命名空間是一個(gè)抽象概念,不必跟文件目錄一一對應(yīng)。大多數(shù)PHP Components都是根據(jù)PSR-4 autoloader standard來組織subnamespaces與文件目錄的映射關(guān)系的。
從技術(shù)上來說,namespaces僅僅是一個(gè)PHP語言的符號,PHP解釋器使用這個(gè)符號來作為一組classes/interfaces/functions/constants集合的前綴,僅此而已。
Namespaces are important because they let us create sandboxed code that works alongside other developer's code. This is the cornerstone concept of the modern PHP component ecosystem.
Helpful Tips
1. Multiple imports
bad:
<code class="php?linenums hljs tex"><?phpuse Symfony<span class="hljs-command">\Component</span><span class="hljs-command">\HttpFoundation</span><span class="hljs-command">\Request</span>, Symfony<span class="hljs-command">\Component</span><span class="hljs-command">\HttpFoundation</span><span class="hljs-command">\Response</span>, Symfony<span class="hljs-command">\Component</span><span class="hljs-command">\HttpFoundation</span><span class="hljs-command">\Cookie</span>;</code>
good:
<code class="php?linenums hljs tex"><?phpuse Symfony<span class="hljs-command">\Component</span><span class="hljs-command">\HttpFoundation</span><span class="hljs-command">\Request</span>; use Symfony<span class="hljs-command">\Component</span><span class="hljs-command">\HttpFoundation</span><span class="hljs-command">\Response</span>; use Symfony<span class="hljs-command">\Component</span><span class="hljs-command">\HttpFoundation</span><span class="hljs-command">\Cookie</span>;</code>
2. one class per file
3.Global namespace
如果我們引用一個(gè)沒有命名空間的class/interface/function/constant,PHP會首先假設(shè)這個(gè)class/interface/function/constant在當(dāng)前的命名空間中。如果在當(dāng)前命名空間中沒有找到,PHP才會開始resolve。而對于那些沒有沒有命名空間的代碼,PHP認(rèn)為他們存在于global namespace。
PSR-4
Code to an interface
An interface is a contract between tow PHP objects that lets one object depend not on what another object is but, instead, on what another can do.
Trait
A trait is a partial class implementation(i.e., constants, properties, and methods) that can be mixed into one or more existing PHP classes. Traits work double duty: they say what a class can do (like an interface), and they provide a modular implementation (like class).
相對Android開發(fā),我最喜歡的iOS中一個(gè)特性就是category,PHP的trait就是有點(diǎn)類似于category,不過還是不太一樣的:
1. OC只能針對特定的類進(jìn)行擴(kuò)展,而PHP的trait可以將代碼單元注入到任意的不相關(guān)的類中;
2. 同時(shí)OC中的category并不能直接實(shí)現(xiàn)屬性的擴(kuò)展,而PHP的trait則能實(shí)現(xiàn)常量,屬性,以及方法;
3. PHP的trait跟OC的category根本上來說用途是不一樣的,OC是對現(xiàn)存類直接擴(kuò)展,不需要繼承實(shí)現(xiàn)類。而PHP的trait需要在類的定義中使用 use
來明確。
跟class和interface的定義一樣,on trait per file。
Generators
Generators are easy to create because they are just PHP functions that use the yield keyword one or more times. Unlike regular PHP functions, generators never return a value. They only yield values.
這個(gè)概念并不陌生,Python包括Swift都有這個(gè)特性,可以用在對大量數(shù)據(jù)的迭代中,動(dòng)態(tài)去獲取數(shù)據(jù),而不是一次性生成,避免內(nèi)存的浪費(fèi)。
在每次迭代的過程中,PHP都會讓Generator實(shí)例計(jì)算和提供下一個(gè)迭代值。在這個(gè)過程中,當(dāng)generator執(zhí)行到y(tǒng)ield value的時(shí)候,generator會暫停它的內(nèi)部狀態(tài)的執(zhí)行。只有g(shù)enerator被要求提供下一個(gè)迭代值的時(shí)候,它才會繼續(xù)它的內(nèi)部狀態(tài)的執(zhí)行。generator就這樣反復(fù)pasuing 和 resuming,直到到達(dá)generator的函數(shù)定義的尾部或empty的時(shí)候,generator才會結(jié)束執(zhí)行。
Generators are a tradeoff between versatility and simplicity. Generators are forward-only iterators.
Closures
A closure is a function that encapsulates its surrounding state at the time it is created. The encapsulated state exists inside the closure even when the closure lives after it original environment ceases to exist.
這里的閉包是指Closure和Anonymous functions。上面是作者對于閉包的解釋,感覺非常準(zhǔn)確,比我看到的大多數(shù)解釋都要簡單清晰。閉包在日常業(yè)務(wù)開發(fā)中非常有用,可以非常方便替換我們經(jīng)常需要用到的delegate設(shè)計(jì)模式,不需要再去定義一個(gè)interface,然后再實(shí)現(xiàn)這個(gè)interface,再把對應(yīng)的對象指針傳遞過去。而是通過Closure,只需要簡簡單單傳遞一段代碼即可,這個(gè)極大簡化了日常業(yè)務(wù)開發(fā)。所以目前iOS開發(fā)中,大家通常都會使用block來代替delegate設(shè)計(jì)模式。
PHP Closure or Anonymous function 跟PHP function的定義語法是一樣的,但是實(shí)際上 Closure 的背后是Closure class的實(shí)例,所以Closure被認(rèn)為是first-class value types。
Attach State : PHP的Closure不會automatically enclose application state,不像JavaScript/OC那樣會capture作用域之外的變量。而是,you must manually attach state to a PHP closure with the closure object's bindTo() method or the use keyword.
需要注意的是,PHP closures是objects。而我們之所以能讓一個(gè)closure 實(shí)例變量進(jìn)行調(diào)用,是因?yàn)檫@個(gè)對象實(shí)現(xiàn) __invoke()
magic method,當(dāng)我們在closure實(shí)例變量后面跟著一個(gè) ()
的時(shí)候,closure實(shí)例變量就會尋找并且調(diào)用__invoke()
方法,例如 $closure("Jason")
。
同樣,由于PHP closure是objects。所以,在closure內(nèi)部我們也可以通過 $this
訪問closure的各種內(nèi)部狀態(tài),但是這個(gè)狀態(tài)是非常boring。同時(shí),closure的bindTo()
方法可以有一些非常有趣的特殊用法,This method lets us bind a Closure object's internal state to a different object. The bindTo() method accepts an important second argument that specifies the PHP class of the object to which the closure is bound.This lets the closure access protected and private member variables of the object to which it is bound.
。這個(gè)用法有點(diǎn)類似JavaScript的bind方法,可以改變Closure object的 $this 指針指向。
bindTo()這個(gè)有趣的用法,經(jīng)常各種PHP框架的路由所采用,例如:
<code class="php?linenums hljs xml"><span class="php"><span class="hljs-preprocessor"><?</span> php<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">App</span>{</span> <span class="hljs-keyword">protected</span> <span class="hljs-variable">$routes</span> = <span class="hljs-keyword">array</span>(); <span class="hljs-keyword">protected</span> <span class="hljs-variable">$responseStatus</span> = <span class="hljs-string">'200 OK'</span>; <span class="hljs-keyword">protected</span> <span class="hljs-variable">$responseContentType</span> =<span class="hljs-string">'text/html'</span>; <span class="hljs-keyword">protected</span> <span class="hljs-variable">$responseBody</span> = <span class="hljs-string">'Hello world'</span>; <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addRoute</span><span class="hljs-params">(<span class="hljs-variable">$routePath</span>, <span class="hljs-variable">$routeCallback</span>)</span> {</span> <span class="hljs-comment">// 將Closure bind到App類上</span> <span class="hljs-variable">$this</span>->routes[<span class="hljs-variable">$routePath</span>] = <span class="hljs-variable">$routeCallback</span>->bindTo(<span class="hljs-variable">$this</span>, <span class="hljs-keyword">__CLASS__</span>); } <span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dispatch</span><span class="hljs-params">(<span class="hljs-variable">$currentPath</span>)</span> {</span> <span class="hljs-keyword">foreach</span> (<span class="hljs-variable">$this</span>->routes <span class="hljs-keyword">as</span> <span class="hljs-variable">$routePath</span> => <span class="hljs-variable">$callback</span>) { <span class="hljs-keyword">if</span> (<span class="hljs-variable">$routePath</span> === <span class="hljs-variable">$currentPath</span>) { <span class="hljs-variable">$callback</span>(); } } <span class="hljs-comment">// 這里返回的state是在callback內(nèi)修改過的</span> header(<span class="hljs-string">'HTTP/1.1 '</span>.<span class="hljs-variable">$this</span>.responseStatus); header(<span class="hljs-string">'Content-type: '</span>.<span class="hljs-variable">$this</span>.responseContentType); header(<span class="hljs-string">'Content-length: '</span>.mb_strlen(<span class="hljs-variable">$this</span>->responseBody)); <span class="hljs-keyword">echo</span> <span class="hljs-variable">$this</span>->responseBody; }}<span class="hljs-comment">// 添加注冊一個(gè)路由</span><span class="hljs-preprocessor"><?php</span><span class="hljs-variable">$app</span> = <span class="hljs-keyword">new</span> App();<span class="hljs-variable">$app</span>->addRoute(<span class="hljs-string">'/users/josh'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> {</span> <span class="hljs-comment">// 因?yàn)檫@個(gè)route是bindTo到App class上的,所以這里直接訪問$this修改 App 的內(nèi)部state</span> <span class="hljs-variable">$this</span>->responseContentType = <span class="hljs-string">'application/json;charset=utf8'</span>; <span class="hljs-variable">$this</span>->responseBody = <span class="hljs-string">'{"name": "Josh"}'</span>;});<span class="hljs-variable">$app</span>->dispatch(<span class="hljs-string">'/users/josh'</span>);</span></code>
Zend Opcache
從PHP 5.5.0開始,PHP引入了內(nèi)置的bytecode cache支持,叫做 Zend OPcache
。PHP解釋器在執(zhí)行PHP腳本的時(shí)候,會首先把PHP代碼編譯為Zend Opcodes (machine-code instructions),然后才會執(zhí)行bytecode。在所有請求中,PHP解釋器都需要這樣處理所有的PHP文件,read/parse/compiles,然而我們可以通過把PHP文件預(yù)編為PHP bytecode來省略這個(gè)開銷,這就是Zend OPcache
。
Zend OPcache
的使用非常簡單,在我們配置之后,它就會在內(nèi)存中自動(dòng)緩存precompiled PHP bytecode,在可用的情況就會直接執(zhí)行這個(gè)PHP bytecode,而不需要再去編譯PHP代碼。
具體配置去google吧,有一點(diǎn)需要注意的是,如果同時(shí)配置了 Xdebug的話,在php.ini文件中,需要在Xdebug之前加載Zend OPcache extension擴(kuò)展。
Built-in HTTP server
PHP從5.4.0引入了內(nèi)置的HTTP server,所以我們在不配置Apache或者nginx的情況下就直接預(yù)覽PHP程序。
<br>Remember, the PHP built-in server is a web server. It speaks HTTP, and it can serve static assets in addition to PHP files. It's a great way to write and preview HTML locally without installing MAMP, WAMP, or a heavyweight web server. <br>
要使用內(nèi)置的HTTP server非常簡單,在工程的根目錄下,執(zhí)行下面的命令即可:
<code class="bash hljs ">php -S localhost:<span class="hljs-number">4000</span></code>
如果要讓本地網(wǎng)絡(luò)的其他設(shè)備訪問PHP web server,我們可以這么啟動(dòng):
<code class="bash hljs ">php -S <span class="hljs-number">0.0</span>.<span class="hljs-number">0.0</span>:<span class="hljs-number">4000</span></code>
如果我們希望通過 PHP INI 配置文件去做一些特殊配置,可以通過下面命令來啟動(dòng):
<code class="bash hljs ">php -S localhost:<span class="hljs-number">8000</span> -c app/config/php.ini</code>
我們也可以通過Router Scripts來實(shí)現(xiàn)一些特殊的路由需求,可以通過下面的命令啟動(dòng):
<code class="bash hljs ">php -S localhost:<span class="hljs-number">8000</span> router.php</code>
在PHP代碼中,我們可以通過php_sapi_name()
來判斷:
<code class="php?linenums hljs xml"><span class="php"><span class="hljs-preprocessor"><?php</span><span class="hljs-keyword">if</span> (php_sapi_name() === <span class="hljs-string">'cli-server'</span>) { <span class="hljs-comment">// PHP web server</span>} <span class="hljs-keyword">else</span> { <span class="hljs-comment">// Other web server</span>}</span></code>
Part 2. Good Pratices
Standards
PHP-FIG
PHP-FIG (PHP Framework Interop Group): The PHP-FIG is a group of PHP framework representatives who, according to the PHP-FIG website, "talk about the commonalities between our projects and find ways we can work together."
PHP-FIG是由很多不同PHP framework開發(fā)者組成的一個(gè)開放組織,他們提出的recommendations,不是標(biāo)準(zhǔn)或也不是要求,更像是best pratices的建議集合。不過,目前比較流行大多是PHP框架,比如Laravel或Symfony,都遵守了這些recommendations,所以這個(gè)感覺更像是Modern PHP事實(shí)上的標(biāo)準(zhǔn),如果要使用PHP的很多工具和龐大的各種開源庫,最好采用這個(gè)標(biāo)準(zhǔn)。
The PHP-FIG's mission is framework interoperability. And framework interoperability means working together via interfaces, autoloading, and style.
正如下面所說,PHP-FIG的使命就是不同framework之間的互通,讓不同框架可以很容易結(jié)合在一起使用。而實(shí)現(xiàn)互通目前主要通過三個(gè)方面來入手:interfaces, autoloading, style:
- Interfaces:
Interfaces enable PHP developers to build, share, and use specialized components instead of monolithic frameworks
,基于interfaces,我們可以做到直接使用某個(gè)框架的某個(gè)組件,比如Laravel的HTTP的處理部分就是直接使用 Symfony Frameworks的 symfony/httpfoundation 組件,而不用把整個(gè)Symfony都集成到Laravel之內(nèi)。 - Autoloading:
PHP frameworks work together via autoloading. Autoloading is the process by which a PHP class is automatically located and loaded on-demand by the PHP interpreter during runtime
,在autoloading標(biāo)準(zhǔn)出來之前,PHP組件和框架都是基于\__autoload()或spl_autoload_register()
方法來實(shí)現(xiàn)自己獨(dú)特的autoloaders,所以我們要使用一個(gè)第三方組件的時(shí)候,需要首先去研究一下它的autoloaders的實(shí)現(xiàn)。 - Style:
PHP frameworks work together via code style.
PSR
PSR是 PHP standards recommendation
的縮寫,是PHP-FIG提出的recommendations文檔,例如PSR-1,PSR-2等。每個(gè)PHP-FIG recommendation都是為了解決某個(gè)大多數(shù)PHP框架開發(fā)中常遇到的問題而提出的。
目前在PHP-FIG的官方網(wǎng)站上,http://www.php-fig.org/psr/ ,可以看到所有的recommendations,目前被采用的有下面幾個(gè):
具體的PSR文檔內(nèi)容,可以參考官方網(wǎng)站,PSR-1/2/3/4 幾個(gè)文檔有中文翻譯:
文檔 | 原文 | 中文翻譯 |
---|---|---|
PSR-1 Basic Coding Standard | https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md | https://segmentfault.com/a/1190000002521577 |
PSR-2 Coding Style Guide | https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md | https://segmentfault.com/a/1190000002521620 |
PSR-3 Logger Interface | https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md | https://segmentfault.com/a/1190000002521644 |
PSR-4 AutoLoading Standard | https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md | https://segmentfault.com/a/1190000002521658 |
PSR-1 Basic Coding standard
PHP tags : 使用
PSR-2 Strict Code Style
Implement PSR-1 : 要求必須采用PSR-1
Indentation: 采用4個(gè)空格字符作為縮進(jìn)
Files and lines : 必須使用Unix linefeed(LF)作為結(jié)尾;文件最后必須以空行作為結(jié)束;不能使用尾部 ?> PHP tag;每行盡量不要超過80個(gè)字符,最多不能超過120個(gè)字符;每行結(jié)尾不能包含空格;
Keywords: 所有的PHP關(guān)鍵字都必須小寫
Namespaces: 每個(gè)namespace聲明后面都必須跟著一個(gè)空行;使用use來import or alias namespaces的時(shí)候,必須在use聲明后面跟一個(gè)空行;
Classes: 定義類時(shí),開始的大括號(opening bracket)必須新起一行,結(jié)束的大括號(closing bracket)必須在類體定義后面新起一行;extents/implements關(guān)鍵字必須跟在類名定義的后面;例如:
<code class="php?linenums hljs xml"><span class="php"><span class="hljs-preprocessor"><?php</span><span class="hljs-keyword">namespace</span> <span class="hljs-title">My</span>\<span class="hljs-title">App</span>;<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Administrator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">User</span> {</span> <span class="hljs-comment">// Class definition body</span>}</span></code>
Methods: 方法定義的大括號規(guī)則與類定義類似,opening brackets和closing brackets都必須新起一行。
Visibility: 對類中定義的全部property和method都必須聲明可見性(visibility),可見性是public, protected, private其中的一個(gè);abstract / final 必須寫在visibility之前;static必須寫在visibility之后;
Control structures : 所有的control structure keyword (if/elseif/else/switch/case/while/do while/for/foreach/try/catch)的后面都必須一個(gè)空字符;大括號的規(guī)則與class定義不同,opening brackets跟control structure keyword必須在同一行,而closing bracket必須另新一行;
我們可以通過IDE的格式化工具來讓代碼格式化,實(shí)現(xiàn)PSR-1和PSR-2的code style。我經(jīng)常使用的工具PHPStorm就可以設(shè)置。還有一些其他工具,比如 PHP-CS-Fixer 或 PHP Code Sniffer
PSR-3 Logger Interface
PSR-3 is an interface, and it prescribes methods that can be implemented by PHP logger components.
PSR-4 Autoloaders
An autoloader is a strategy for finding a PHP class, interface, or trait and loading it into the PHP interpreter on-demand at runtime. PHP components and frameworks that support the PSR-4 autoloader standard can be located by and loaded into the PHP interpreter with only one autoloader.
關(guān)于PSR-4,看官方文檔之后感覺理解很困惑,本書的作者的解釋就非常簡潔: The essence of PSR-4 is mapping a top-level namespaces prefix to a specific filesystem directory.
,簡單來說,就是設(shè)定了一個(gè)namespaces前綴和某個(gè)特定的文件目錄之間的映射關(guān)系,然后在這個(gè)namespace前綴之下如果還有更多的sub namespace,這些sub namespaces就會跟這個(gè)特定的目錄下面的子目錄一一映射起來。例如,\Oreilly\ModernPHP namespace與 src/ 物理路徑一一映射,那么\Oreilly\ModernPHP\Chapter1對應(yīng)的文件夾就是src/Chapter1,而\Oreilly\ModernPHP\Chapter1\Example類對應(yīng)的文件路徑就是src/Chapter1/Example.php文件。
PSR-4 lets you map a namespace prefix to a filesystem directory. The namespace prefix can be one top-level namespace. The namespace prefix can also be a top-level namespace and any number of subnamespaces. It's quite flexible.
Components
Components
Modern PHP is less about monolithic framework and more about composing solutions from specialized and interoperable components.
What Are Components?: A component is a bundle of code that helps solve a specific problem in your PHP application.
框架與Components:如果我們正在創(chuàng)建一個(gè)小項(xiàng)目,可以直接使用一些PHP Components集合來解決問題;如果我們正在進(jìn)行一個(gè)多人合作開發(fā)的大項(xiàng)目,我們可以通過使用一個(gè)Framework;但這都不是絕對的,應(yīng)該根據(jù)具體問題來解決。
Packagist:跟其他語言的包管理機(jī)制一樣,例如Maven,也有一個(gè)網(wǎng)站 https://packagist.org/ 讓我們搜索我們需要的PHP Components的相關(guān)信息??偹苤脑?,Packagist在國內(nèi)很不穩(wěn)定,可以使用國內(nèi)的全量鏡像來代替,http://www.phpcomposer.com/ 。
Composer
Composer is a dependency manager for PHP components taht runs on the command line
,跟其他現(xiàn)代語言一樣,PHP使用Composer來做依賴管理,類似的有iOS中的Cocoapods,Android中的Maven/gradle,前端的npm,ruby的gem,這些工具可以大大簡化我們管理第三方庫的成本。于是,當(dāng)我們在Packagist上面找到我們需要的Components之后,就可以通過Composer來使用這個(gè)庫。
當(dāng)我們使用Composer來添加第三方Component的時(shí)候,Composer除了會自動(dòng)幫我們下載需要的PHP Components之外,還會自動(dòng)幫我們創(chuàng)建一個(gè)符合PSR-4的Autoloader。
跟Cocoapods類似,Cocoapods使用Podfile來指定需要依賴的第三方庫,以及保存有當(dāng)前使用的具體的第三方庫的版本號。所以我們需要把這兩個(gè)文件都加入到版本控制中進(jìn)行管理,確保不同成員/CI/開發(fā)環(huán)境等不同地方大家使用第三方庫版本的一致性。對應(yīng)Composer中的文件就是 composer.json以及composer.lock。這里需要注意的是composer install 和 composer update 命令的差別:
* composer install,不會安裝比composer.lock中列出的更高版本的Components;
* composer update,會更新你的components到最新的穩(wěn)定版,同時(shí)也會更新composer.lock文件為最新的PHP components版本號。
Semantic Versioning
Modern PHP Components 使用 Semantic Versioning scheme,同時(shí)包含了用小數(shù)點(diǎn)(.)分隔的三個(gè)數(shù)字,比如 1.13.2。同時(shí),這個(gè)也是很多其他語言開源庫的版本規(guī)則,對這個(gè)一直比較好奇,終于在Modern PHP中看到了相應(yīng)的解釋。
- major release number:第一個(gè)數(shù)字是major release number,只有當(dāng)PHP Component發(fā)生不再向前兼容的更新時(shí),才需要增加這個(gè)版本號。
- minor release number:第二個(gè)數(shù)字是minor release number,當(dāng)PHP Component發(fā)生一些小的功能更新,并且沒有破壞版本兼容時(shí),增加這個(gè)版本號。
- patch release number:最后一個(gè)數(shù)字是patch release number,當(dāng)發(fā)生版本兼容的bug修復(fù)的時(shí)候,增加這個(gè)版本號。
Create PHP Components
這部分跟iOS創(chuàng)建自己的spec非常相似,并不是非常復(fù)雜的問題,參考書或者官方文檔很容易就能發(fā)布

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

TostaycurrentwithPHPdevelopmentsandbestpractices,followkeynewssourceslikePHP.netandPHPWeekly,engagewithcommunitiesonforumsandconferences,keeptoolingupdatedandgraduallyadoptnewfeatures,andreadorcontributetoopensourceprojects.First,followreliablesource

PHPbecamepopularforwebdevelopmentduetoitseaseoflearning,seamlessintegrationwithHTML,widespreadhostingsupport,andalargeecosystemincludingframeworkslikeLaravelandCMSplatformslikeWordPress.Itexcelsinhandlingformsubmissions,managingusersessions,interacti

TosettherighttimezoneinPHP,usedate_default_timezone_set()functionatthestartofyourscriptwithavalididentifiersuchas'America/New_York'.1.Usedate_default_timezone_set()beforeanydate/timefunctions.2.Alternatively,configurethephp.inifilebysettingdate.timez

TovalidateuserinputinPHP,usebuilt-invalidationfunctionslikefilter_var()andfilter_input(),applyregularexpressionsforcustomformatssuchasusernamesorphonenumbers,checkdatatypesfornumericvalueslikeageorprice,setlengthlimitsandtrimwhitespacetopreventlayout

ThePhpfunctionSerialize () andunserialize () AreusedtoconvertcomplexdaTastructdestoresintostoraSandaBackagain.1.Serialize () c OnvertsdatalikecarraysorobjectsraystringcontainingTypeandstructureinformation.2.unserialize () Reconstruct theoriginalatataprom

You can embed PHP code into HTML files, but make sure that the file has an extension of .php so that the server can parse it correctly. Use standard tags to wrap PHP code, insert dynamic content anywhere in HTML. In addition, you can switch PHP and HTML multiple times in the same file to realize dynamic functions such as conditional rendering. Be sure to pay attention to the server configuration and syntax correctness to avoid problems caused by short labels, quotation mark errors or omitted end labels.

The key to writing clean and easy-to-maintain PHP code lies in clear naming, following standards, reasonable structure, making good use of comments and testability. 1. Use clear variables, functions and class names, such as $userData and calculateTotalPrice(); 2. Follow the PSR-12 standard unified code style; 3. Split the code structure according to responsibilities, and organize it using MVC or Laravel-style catalogs; 4. Avoid noodles-style code and split the logic into small functions with a single responsibility; 5. Add comments at key points and write interface documents to clarify parameters, return values ??and exceptions; 6. Improve testability, adopt dependency injection, reduce global state and static methods. These practices improve code quality, collaboration efficiency and post-maintenance ease.

Yes,youcanrunSQLqueriesusingPHP,andtheprocessinvolveschoosingadatabaseextension,connectingtothedatabase,executingqueriessafely,andclosingconnectionswhendone.Todothis,firstchoosebetweenMySQLiorPDO,withPDObeingmoreflexibleduetosupportingmultipledatabas
