PHP 與 Node.js
TL;DR :PHP 不會立即消失,但它的地位會被新生的 Node.js 進一步削弱。
當互聯網在 2000 年代爆炸式增長時,PHP 是一個東西所有酷孩子 做過。這是極具革命性的,因為:
- 它是一種解釋型語言,不像 C++ 或 Java,需要編譯源代碼
- 通過在模板文件中混合
<%php ... %>
,它可以直接與 HTML 一起使用 標記標籤 - 它在具有 Linux、Apache、MySQL 和 PHP (LAMP) 堆棧的 Apache 服務器上擁有廉價的共享託管服務提供商
- 它具有比面向對象編程更容易學習的函數性質
多年來,PHP 及其應用程序成為一種可怕的技術,容易受到安全威脅(例如 SQL 注入)、缺乏集中的打包註冊表(Composer 是受 Node Package Manager 的啟發嗎?)、不一致的 API 和低於標準的性能。 PHP 有很多更好的替代品,例如 Ruby on Rails 和 Django,但沒有什麼比 Node.js 更平易近人了。
對於那些不熟悉 Node.js,或者聽說過但不能完全理解這個概念的人,這裡是我的類比:
如今,Node.js 勢頭強勁。該平台使用 JavaScript。它是功能性的,並且它的非阻塞 I/O 機制可以提供更好的性能。 Node.js 帶有強大的 Node Package Manager 解決方案和規範,即 ECMAScript。
由於 Node.js 是底層技術,無法直接與 Struts、Rails 或 Django 等複雜框架相媲美。
因此,許多人,無論是軟件工程師還是企業家,都經常面臨“使用什麼技術堆棧的決定 ” 在這篇 PHP 與 Node.js 的文章中,我們將從不同的角度來比較蘋果與蘋果的做法,例如:
- 語法
- 上下文切換
- 模塊
- 生態系統
- 框架
- 實時應用
- 數據庫應用
- 第三方服務應用
- 網絡服務器
- 託管
- 性能
語法
兩個平台都可以通過 $ php -i
訪問命令行界面 和 $ node
.
此代碼段在 PHP 中打印“Hello World”:
echo 'Hello World';
這將在 Node.js 中輸出相同的短語:
console.log('Hello World');
注意:在 JavaScript 中,分號是可選的,除非在 for
內 循環和立即調用的函數表達式之前(IIFE)。
PHP中的休眠函數腳本示例:
echo "a"."\n";
sleep(2);
echo "b"."\n";
echo "c"."\n";
上面的代碼會輸出:
[旁注]
閱讀博客文章很好,但觀看視頻課程更好,因為它們更具吸引力。
許多開發人員抱怨 Node.js 上缺乏負擔得起的高質量視頻材料。觀看 YouTube 視頻會讓人分心,花 500 美元購買 Node 視頻課程很瘋狂!
去看看 Node University,它有關於 Node 的免費視頻課程:node.university。
[旁注結束]
a
然後延遲 2 秒後:
b
c
如果我們嘗試在 Node.js 中重寫代碼:
console.log('a')
setTimeout(function() {
console.log('b')
},2000)
console.log('c')
此代碼段將打印:
a
c
並有 2 秒的延遲,它將打印:
b
注意 :在 JavaScript 中,console.log()
自動添加行尾符號。
for
PHP 中的循環可能如下所示:
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
它們在 Node.js 中驚人地相似:
for (var i = 0; i <= 10; i++) {
console.log(i);
}
在 PHP 中創建數組:
$users = array(
array('name' => 'John', 'id' => 3940),
array('name' => 'Peter', 'id' => 8904)
);
在 Node.js 中創建數組:
var users = [
{ name: 'John', id: 3940 },
{ name: 'Peter', id: 8904 }
]
在 PHP 中遍歷數組:
for($i = 0; $i < count($users); ++$i) {
$users[$i]['id'] = mt_rand(000000, 999999);
}
在 Node.js 中遍歷數組:
for (var i; i < arr.length; i++) {
users[i] = Math.floor(Math.random()*1000000);
}
或者以功能的方式:
users.forEach(function(user, i){
users[i] = Math.floor(Math.random()*1000000);
})
在 PHP 中聲明一個函數:
function hello($name) {
echo "Hi ".$name;
}
hello("Peter"); //outputs Hi Peter
在 Node.js 中聲明一個函數:
function hello(name) {
console.log('Hi' + name);
}
hello('Peter'); //outputs Hi Peter
在 PHP 中聲明一個新對象:
class foo {
function do_foo() {
echo "Doing foo.";
}
}
$bar = new foo;
$bar->do_foo();
在 Node.js 中聲明一個新對象:
var foo = function () {
return {
do_foo: function () {console.log('Doing foo');}
};
};
var bar = foo();
bar.do_foo();
注意 :Node.js/JavaScript 中沒有類,因為對象直接從其他對象繼承(原型繼承)。實例化模式有偽經典、函數式(上)、經典等多種實例化模式。
PHP 中帶有 PDO 數據庫連接庫的數據庫片段:
$pdo = new PDO('sqlite:users.db');
$stmt = $pdo->prepare('SELECT name FROM users WHERE id = :id');
$stmt->bindParam(':id', $_GET['id'], PDO::PARAM_INT); //<-- Automatically sanitized by PDO
$stmt->execute();
帶有 Mongoskin MongoDB 庫的 Node.js 數據庫腳本:
//assuming we use Connect/Express middleware for req.query
var db = require('mongoskin').db('localhost:27017/db');
db.collection('users').find({_id: req.query.id}).toArray(function(err, results) {
if (err) throw err;
console.log(results);
});
上下文切換
不同環境和語言之間的切換歸因於編寫軟件代碼時效率的下降。許多研究和個人軼事觀察表明,中斷會對程序員的表現產生負面影響。學習和記住的語言更少,流程更流暢,代碼更好!有關此主題的更深入文章,您可能需要查看被認為有害的人工任務開關和多任務神話。
PHP
使用 LAMP 堆棧,即 Linux、Apache、MySQL 和 PHP,除了 強制,開發人員還必須掌握至少兩種以上的語言,即 PHP 和 SQL 以及無處不在的 HTML、CSS 和 JavaScript。
Node.js
Node.js 非常擅長減少上下文切換,因為與 MongoDB 一起,這個堆棧只能在 one 中運行 語言:JavaScript!
MongoDB shell 命令示例(由 $ mongo
調用 ):
> db.users.find({});
> db.users.insert({name: 'Azat', email: '[email protected]'})
> db.users.update({name:'Azat'},{$set:{email:'[email protected]'}})
模塊
PHP
有 PEAR,一個在全球服務器上安裝軟件包的老牌系統,以及一個更好的 Composer 替代品。
在其他情況下,開發人員必須在各種網站上尋找模塊(或他們稱之為組件),並通過放置 *.php
來手動管理它們 文件到他們項目的子文件夾中。不幸的是,這一切都不是很乾淨。
Node.js
Node.js 帶有一個名為 NPM 的卓越且可靠的包管理系統及其註冊表 npmjs.org,它易於使用和發布。一切都通過 package.json
進行管理 文件並在本地進行版本控制,除非我們使用 -g
安裝 CLI 工具 選項。
PHP 和 Node.js 都是函數式語言,在 PHP 中添加 OOP 是相對較晚的。
生態系統
PHP
這可能是 PHP 仍然擊敗 Node.js 的最重要領域之一。有許多令人驚嘆的開源應用程序,例如 WordPress、大量免費腳本、優質工具和書籍。
Node.js
Node.js 的增長速度比任何其他平台/語言都快。這主要是由於保持模塊最小化並且只執行一小部分任務的理念。其他因素可能包括:
- 前端 JavaScript 在 Web 開發人員中大受歡迎
- 規範的存在,以及在語言存在多年期間積累的大量 JavaScript 資源和專家(例如 Doug Crockford)
- 協作的 GitHub 開源社區,基於以前不存在的出色分佈式版本控制系統
- 易於使用 NPM,例如發布 NPM 模塊運行
$ npm publish
因此,有人預測 Node.js 在貢獻的絕對數量上會超過其他語言。
框架
擁有豐富的工具和經過驗證的庫供我們使用非常重要。
PHP
CakePHP 和 Zend 浮現在腦海中,更多選擇有一個廣泛的列表。
Node.js
競爭環境相對公平,Express.js 是最受歡迎的選擇,全棧 MVC 框架 Meteor 和 Derby 展示了通往未來的道路。
實時應用
PHP
對於 PHP,還有 Node.js 依賴的 Elephant.io 和其他一些方法。原生 PHP 和 websockets 的問題在於 Apache 和 ISS——PHP 通常作為一個模塊運行——在構建時並沒有真正考慮到持久連接。因此,開發者必須使用獨立的進程,例如:Apache WebSocket 或 Ratchet。
Node.js
使用 Socket.IO 庫的 Node.js 堆棧、Express.js 框架和 Handlebars 反應式模板引擎,構建實時應用程序變得輕而易舉。在 Meteor 和 Derby 項目中,通過將前端和後端代碼庫與持久層相結合,實時應用程序構建更進一步,從而大大降低了複雜性並大大加快了開發速度。
數據庫應用
PHP
PHP 與 MySQL 等傳統/關係數據庫有著悠久而富有成果的歷史,因此堆棧 LAMP 的名稱 — Linux、Apache、MySQL 和 PHP。
Node.js
Node.js 與 MongoDB 等 NoSQL 數據庫很自然。
根據 MySql 與 MongoDB 性能基準(MySQL)、簡單測試:MongoDB 與 MySQL(MongoDB)和 MongoDb 與 MySql – Fight!!!(MongoDB)文章的用例,數據庫的性能在某種程度上彼此可比。但是,MongoDB 更適合分佈式數據庫,並且具有高度可擴展性。額外的好處是,沒有固定架構,NoSQL 數據庫非常適合雲計算、原型設計和敏捷項目。
第三方服務應用
PHP
與許多傳統語言一樣,PHP 的流程被阻塞,直到遠程服務器響應,因此需要多線程。
注意 :某些語言在使用特殊庫/框架(例如用於 Ruby 的 EventMachine 或用於 Python 的 Twisted)時提供此功能。但是,它們非常複雜,並且不是通過平台從頭開始構建的。
Node.js
相反,由於非阻塞 I/O,Node.js 可以處理多個請求並 make 作為客戶端向第三方服務(例如 Twitter、Amazon)發送多個請求,只需一個執行線程。
網絡服務器
PHP
從 PHP 5.4 及更高版本開始,我們可以開始使用內置的開發服務器:
$ php -S localhost:8000
假設我們在那個文件夾中有 index.php:
<?php
echo 'Hello World';
?>
對於 5.4 之前的版本,有 MAMP 和 XAMPP 等“一體化”工具。
至於生產環境,PHP不能自己運行。與 PHP 一起使用的最流行的技術之一是 Apache 和 nginx,其中 PHP 只是 Apache Web 服務器的一個模塊。我個人對 Apache 的體驗是,它的學習曲線很陡峭,而且雖然非常可配置,但默認情況下這些配置很容易出現安全漏洞。
Node.js
Node.js 是為網絡應用程序從頭開始創建的,並且有一組核心模塊來編寫 Web 服務器。
啟動 Node.js 服務器:
$ node .
假設我們在這個文件夾中的 index.js 文件有:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
在生產環境中,Node.js 可以作為服務運行在 SmartOS 或 Linux(如 Ubuntu)上。
注意 :在帶有集群和/或外部模塊的 Node.js 中,多線程是絕對可行的。
託管
PHP
PHP 的流行主要歸功於所提供的共享託管解決方案的易用性和廉價性。誠然,很難找到一個沒有 LAMP 堆棧的產品。這種商品化有時會導致安全漏洞,並且由於託管服務提供商過度銷售和其他消費者使用惡意代碼而導致停機時間縮短。
平台即服務是更好的選擇,介於成熟的專用服務器和共享主機之間。大部分 PaaS 提供商都支持 PHP 權限。
Node.js
Node.js 在 PaaS 上運行良好,Heroku 和 Nodjitsu 位居榜首。此外,雲基礎設施公司 Joyent(Node.js 的維護者)開發了強大的操作系統 SmartOS,可實現性能爆發、無痛部署和 DTrace 調試。
性能
不用說,性能很重要。該資源展示了不同的基準測試:哪些程序最快?
PHP
PHP 速度比較快,但由於文件系統、數據庫和第三方請求的瓶頸,與 Node.js 及其超快的 Goolge Chrome V8 引擎相比,它失敗得很慘。
例如,當 Facebook 使用 PHP 達到其可擴展性極限時,他們編寫了一個速度極快的 C++ 庫和虛擬機,他們稱之為 HipHop VM,但保留了 PHP API。
Node.js
Node.js 由於其非阻塞 I/O 機制和 Google Chrome V8 引擎技術,速度非常快。我什至聽說 Joyent 開始用 Node.js 重寫他們的一些 C++ 模塊。
結論
PHP 在當時是一項傑出的技術。它的成功和流行來自於:
- 易於學習和使用
- 廉價且簡單的託管大多共享 LAMP
- 大量的開源腳本、應用和庫
與此同時,同樣的事情也導致了它的黃昏。初學者程序員對核心的貢獻不一致地改變了 API,而 OOP/類和模塊管理系統的缺乏抑制了開源社區的發展。缺乏一個領先的框架(想到 Ruby on Rails 作為單一優勢的一個例子)或一個範式也有助於產生大量糟糕的代碼,這些代碼嚴重依賴於混合 PHP 和 HTML 代碼而沒有任何 MVC 風格。另一方面,有很多優秀的 PHP 產品和基礎設施將繼續存在。
Node.js 相對年輕,距離第一次提交只有三年,但它已經是貢獻速度增長最快的平台(絕對數量將在幾年內超過其他語言)。 JavaScript 語言是世界上最流行的語言,並且擁有最大的運行時限制,這當然歸功於這一事實。許多工具被移植到 Node.js,只需對瀏覽器環境進行少量修改或無需修改。此外,關於 JavaScript 基礎知識的優秀書籍(例如 JavaScript:The Good Parts 和 Eloquent JavaScript)再次受到歡迎。
Node.js 非常高效,非常適合構建實時、面向 NoSQL 且可擴展的系統。
免責聲明
我使用過許多技術,包括 Ruby on Rails、Python、Java/J2EE、VB、ASP、Perl,當然還有 PHP。我最複雜的 PHP 項目之一是 openList.co,它涉及使用 MVC 模式與模板引擎、類、數據庫抽象層和 .htaccess
重新路由。然而,在過去的幾年裡,我的重點只專注於 Node.js 和 Backbone.js 等前端 JavaScript 框架。所以我的觀點可能有偏見,請評論您在 PHP 和 Node.js 中的實際項目經驗。
如果您想了解有關 Node.js 的更多信息,請查看我的手工書籍 Rapid Prototyping with JS:Agile JavaScript Development、高級在線培訓 Node Program(Udemy 鏈接)和 HackReactor 的驚人的編碼密集型全日制課程。