【PHP程式設計+MySQL資料庫+PHPMaker整合教學+技術諮詢】 本月特價優惠中! 動態的架站程式時代,要自訂PHP程式頁面有那麼難嗎? MySQL『資料庫』與『資料表』,用PHP程式有那麼難控制嗎? 你不用死背『PHP程式』與『MySQL資料庫』語法也能獨自設計完成! 這是自動化軟體程式的年代 (用PHPMaker 設計在彈指之間就能自動生成整個 PHP 程式系統) 這不是:神話!程式軟體模組取代了這一切複雜的工程。 你可以自己建構自己專屬的: 訂購表單、會員名單、擴增購物車特殊頁面 →POS 系統、CRM 系統、ERP 系統、HRM 系統...等等 (更可以加入數據資源銷售賺錢!) 該是:【見證奇蹟】的時候了! 非親眼所見....真的無法相信此神兵利器!

php程式教學

PHPMaker 2023 的新增功能

PHPMaker 2023 是之前版本的又一次巨大升級。 它加載了許多新功能,內含許多經常請求的功能。 PHPMaker 可能是同類產品中最強大、最靈活的產品,但仍然一如既往地易於使用。

重要訊息 如果您從以前的版本升級,請注意此版本中有一些重大變更,請確保您 閱讀遷移到 v2023 。

 

日曆報告

  • 使用 FullCalendar 進行日曆報告
  • 模態加入、編輯、刪除、檢視事件頁面
  • 事件的跳出視窗
  • 日曆中的上下文選單
  • 預定義的 CSS 類可輕鬆設定事件和跳出視窗的樣式


日曆報告(“dayGridMonth”檢視)


上下文選單


具有符合風格的跳出框

 

增強的控制台報告

  • Ajax 的分頁報告
  • 通過 Ajax 對報告和圖表進行排序
  • 支援匯出
  • 每個報告/圖表的卡片重整/最大化/折疊

 

雙因素身份驗證(使用第三方 API 的電子信件和短信)

除了 Google Authenticator 之外,雙因素身份驗證功能現在還支援:

  • 通過電子信件傳送到一次性密碼
  • 使用第三方 API(例如 AWSSNS)通過 SMS 進行 OTP

 

 

固定頭表(無擴展)

  • 現在內建
  • 提供預定義的 CSS 類,以便輕鬆設定表格高度

 

查詢生成器

  • 構建進階搜尋無法實現的複雜查詢
  • 容許為每個欄位選取搜尋運算符
  • 每個欄位有多個規則
  • 每組欄位之間的 AND/OR 條件
  • 多組規則
  • 組之間的 AND/OR 條件
  • 組的 NOT 條件

 

用於編輯選取記錄的多重編輯

作為多重刪除和多重更新的補充,這一新功能容許通過複選框選取記錄並像網格編輯一樣將它們一起編輯。 還支援模式對話框。

 

現在,您可以在不離開清單頁面的情況下執行網格加入/編輯和新的帶有模式對話框的多重編輯。

 

表和檢視的圖表

不再局限於報告,現在您還可以在表/檢視的清單頁面中建立圖表。

 

 

SAML2 和 Azure AD 的登入提供程式

  • 通過 Azure AD 支援 OAuth2
  • 支援使用 Azure AD 或 SimpleSAMLphp 進行 SAML2 單點登入 (SSO) 和單點註銷 (SLO)

 

改進的資料匯入

  • 使用資料庫事務測試匯入
  • 伺服器傳送到的匯入進度事件
  • 改進了伺服器事件,以便在匯入之前加入自訂步驟

 

匯出API和匯出日誌

  • 匯出API
  • 容許在伺服器上儲存匯出的檔案
  • 匯出日誌表支援匯出檔案的檢索和搜尋
  • 用於匯出的 JWT 令牌的使用者權限和過期時間
  • 支援將圖像匯出為 HTML
  • 支援以壓縮檔形式檢索多個匯出的檔案

 

帶有用戶端裁剪的檔案上傳

 

 

帶文字的條形碼(自訂檢視標籤)

 

 

帶有 <optgroup> 的 SELECT 標籤

 

 

無需重新加載頁面的 Ajax 操作

  • 增強使用者體驗
  • 支援搜尋、分頁、排序
  • 支援內聯和模式加入/複製/編輯/更新/刪除操作

 

無限卷動表(僅限註冊使用者擴展)

  • 清單頁面主表加入無限卷動
  • 使用 Ajax 內聯和模式操作,無需重新加載頁面

 

漂亮的開發錯誤頁面

  • 顯示原始碼、錯誤的堆疊追蹤以及請求的詳細訊息
  • 僅用於開發期間的除錯,不適用於生產

 

新的進階設定

  • HTML 預覽 – 容許在 UI 中禁用 HTML 預覽
  • 代理伺服器位址
  • 代理伺服器連接埠
  • 代理伺服器使用者名
  • 代理伺服器密碼
  • 顯示有錯誤的原始碼(開發)
  • 向表單加入 autocomplete=’off’ 屬性
  • 使用 Ajax 操作(清單頁面)
  • 回退使用者層級權限 – 回退匯入/匯出/搜尋/推送權限到舊清單或管理員權限
  • 啟用搜尋快取的頁面 – 設定哪些頁面使用搜尋快取
  • 匯入最大失敗次數
  • 使用圖像裁剪器進行檔案上傳
  • 匯出資料夾
  • 使用固定頭表
  • 固定標題表高度(CSS 類)
  • LDAP 基本專有名稱
  • Azure 應用程式 ID
  • Azure 應用程式秘密值
  • SAML IdP 元資料 (XML)
  • SAML SP 實體 ID
  • SAML SP X.509 證書檔案
  • SAML SP 私鑰檔案

 

新的/改進的伺服器事件和用戶端腳本

  • 表加載
  • OTP_傳送到
  • 日曆報告的伺服器事件和用戶端腳本
  • 使用者層級權限頁面的用戶端和啟動腳本
  • 用於匯入/匯出的伺服器事件

 

更多的

  • 支援 PHP 7.4、8.0 和 8.1
  • 置換與 PHP 8.1 不相容的過時 Composer 軟體包
  • IS EMPTY 和 IN 搜尋運算符
  • 對 MySQL 使用 FIND_IN_SET()
  • 顯示表/檢視的現用的過濾器
  • 加入選項頁面中的自訂訊息
  • 表名稱作為使用者權限設定頁面中的工具提示
  • .js 和 .css 檔案的 URL 以及版本
  • 支援自訂驗證中的異步功能
  • 語系檔案內含 Tempus Dominus、Select2、jQuery Query Builder 和 FullCalendar 的短語
  • 改進了暫存檔案清理
  • Bootstrap 5.2.1、AdminLTE 3.2 和 Font Awesome 6
  • Dompdf v2.0.0(Dompdf 擴展)
  • Time Lord v6.0.0(日期時間選取器擴展)
  • UI 支援在代理伺服器後面工作
  • 改進了網站上的文件
  • 許多其他小改進

    安裝 PHPMaker 2023 的系統要求:

    PHPMaker

    • Windows 2012R2/2016/2019/8.1/10/11(不支援 ARM 上的 Windows 10/11)
    • .NET Framework 4.6.2 開發人員包 (或更高版本)
    • PHP >= 7.4
    • Composer (v2.3.9 或更高版本)
    • Node.js(內含 npm) (v16 或更高版本,內含 npm v8 或更高版本)
    • WebView2 運行時

    如果您使用 SQL Server 或 Oracle,PHPMaker 需要以下資料庫驅動程式(x86 版本)才能連線到資料庫:

    • Microsoft SQL Server 2012 Native Client (適用於 Microsoft SQL Server),或 Microsoft OLE DB Driver for SQL Server (適用於 Microsoft SQL Server)
    • Oracle 用戶端 (可選,適用於 Oracle)

    伺服器

    • Linux 或 Windows 網路伺服器
    • PHP >= 7.4
    • mod_rewrite (僅適用於 Apache)
    • IIS 重寫 (僅適用於 IIS)
    • 適用於 PHP for SQL Server >= 5.8 的 Microsoft PHP 驅動程式 (需要 Microsoft SQL Server 2012 或更高版本),並且
    • Microsoft ODBC Driver for SQL Server >= 13.1 (需要 Microsoft SQL Server 2012 或更高版本)
    • Oracle 用戶端 (適用於 Oracle)

    瀏覽器

    • Chrome/Edge/Firefox/Safari/Opera(最新)
    • 不支援 Internet Explorer

     

     

HP 是一種伺服器端通用腳本語系,特別適合 Web 開發。

PHP最初的意思是個人首頁。 然而,現在,它代表超文字預處理器。 它是一個遞歸縮寫,因為第一個單詞本身就是縮寫。

於 1994 年建立 PHP 由Rasmus Lerdorf 。 目前 由PHP 開發團隊維護。

從最基本的形式來看, PHP 是一種寫程式語系。 它是一種使用相當廣泛的語系,可以內嵌 HTML 中,這對於任何對 Web 開發感興趣的人來說都是一個巨大的優勢。 HTML 可能很長且包括大量指令,而 PHP 頁麵包括帶有內嵌式代碼的 HTML,使其更易於管理。

PHP 代表超文字預處理器,它本身就很令人困惑。 它實際上並不像聽起來那麼複雜——如果您對 HTML 有基本的瞭解,PHP 應該相當容易學習。 它可以讓您收集、處理和使用資料來建立輸出——基本上它可以讓您與所有頁面進行互動。

那麼為什麼選取 PHP 而不是 JavaScript 呢? 兩者之間的主要區別在於 , JavaScript 在用戶端(例如瀏覽器)上運行,而 PHP 在伺服器上運行,然後生成傳送到用戶端的 HTML。

PHP 能做什麼? 好吧,什麼都行; 然而,它主要用於三個領域:

  • 伺服器端腳本編寫——PHP 的主要領域。 如果您是在家練習的業餘愛好者,這就是方法。
  • 指令行腳本 – 非常適合使用 cron 或任務計劃程式建立的腳本。 也非常適合簡單的文字操作。
  • 編寫桌面應用程式 – PHP 可能不是用於建立桌面應用程式的最佳語系,但它為進階 Web 開發人員提供了比競爭對手更多的選取。

PHP 所需的內容通常就在您的桌面上。 它可以在所有主要操作系統(Linux、Windows 和 Mac OS X 等)上使用。 PHP 還支援許多最廣泛使用的伺服器,因此如果您決定使用它,您可以有多種選取。

毫無疑問,PHP 的最大優點是它對於新手來說很容易學習,同時它具有經驗豐富的專業人士可能需要的所有進階功能。 PHP 的功能也不限於 HTML – 您可以生成從圖像到 Flash 電影的任何內容。

綜上所述

PHP 是一種伺服器端語系

當您在網路瀏覽器中開啟網站時,例如:https://www.insertbilisim.com

Web 瀏覽器向 insertbilisim.com 所在的 Web 伺服器傳送 HTTP 請求。 Web 伺服器接收請求並以 HTML 文件進行響應。

在此示例中,Web 瀏覽器是用戶端,Web 伺服器是伺服器。 用戶端發出頁面請求,伺服器提供服務。

PHP 在 Web 伺服器上運行,處理請求並返回 HTML 文件。

PHP 是一種通用語系

就寫程式語系的用途而言,主要有兩種類型:特定領域語系和通用語系。

特定領域語系用於某些應用領域。 例如,SQL 是一種特定於領域的語系。 主要用於從關係資料庫中查詢資料。 並且SQL不能用於其他目的。

另一方面,PHP 是一種通用語系,因為您可以使用 PHP 開發各種應用程式。

PHP是一種跨平台語系

PHP 可以在所有主要操作系統上運行,內含 Linux、Windows 和 macOS。

您可以將 PHP 與所有領先的 Web 伺服器(如 Nginx、OpenBSD 和 Apache)一起使用。 一些雲環境(例如 Microsoft Azure 和 Amazon AWS)也支援 PHP。

PHP 相當靈活。 它不僅限於處理 HTML。 PHP 內建支援生成 PDF、GIF、JPEG 和 PNG 圖像。

PHP 的一個顯著特點是 MySQL 、PostgreSQL、MS SQL、db2、Oracle Database 和 MongoDB。 它支援多種資料庫

 

為什麼使用 PHP 程式語言?它主要優點有那些?

PHP 編程語言 已經存在了二十多年,並成為一種強大而可靠的解決方案,贏得了大批支持者和崇拜者。 然而,我們需要承認房間裡的 elePHPant:這種編碼語言正在逐漸失去其受歡迎程度,取而代之的是更新的和優化的對應語言。 讓我們看一下這項技術,列出 PHP 的優缺點 ,定義其使用領域,並將其與幾種競爭性開發工具進行比較。

PHP 的用途是什麼?

正如本文已經提到的,PHP 主要用於 Web 開發,並且它在這方面確實很出色。 儘管最初它用於建立動態網頁,但開發人員更喜歡使用這種腳本語系來構建 Web 應用程式 的伺服器端。 然而,PHP本來就是一種通用語系,因此如果需要的話它可能有其他的實現。 例如,可以使用 PHP 構建 桌面應用程式 。 此外,從版本 5 開始,PHP 支援 面向物件寫程式 ,提供了一套全新的功能。

這種腳本語系的多功能性源於其與其他寫程式語系結合的出色能力。 例如,開發人員可以使用 C 語系編寫 PHP 擴展,從而可以加入更多功能。 此外,PHP 擁有大量可用的庫和框架,可以進一步擴展其功能。 此類框架最流行的示例是 Laravel、Symfony、Phalcon、Zend Framework 和 Yii。

Facebook 和 WordPress 是用 PHP 編寫的最著名的兩個軟體示例。 WordPress 是網際網路上最流行的內容管理系統:在所有使用此類系統的網站中, 大約有 48% 採用 WordPress 。 得益於大量的內建和第三方外掛程式,Wordpress 幾乎適合所有角色。 您可以使用它來建立部落格、照片庫、線上商店、新聞門戶和許多其他類型的網站。

的另一個不言自明的示例 Facebook 是PHP 功能 。 這個社交網路早已演變成一個複雜的環境,具有多種功能,內含即時訊息、廣告、部落格、新聞演示、視訊播放等,但仍然基於與其他 Web 技術緊密結合的 PHP 代碼。

PHP 的優點

PHP 的流行是其眾多優點的必然結果,所有這些優點都使其成為強大而有效的開發工具。 簡短原因清單,隨後將進行更詳細的描述。 以下是PHP 成為 Web 應用程式最佳選取的

使用 PHP 的 9 個理由:

  • 許多可用的專家;
  • 大量的參考資料和教育材料;
  • 更好的網站加載速度;
  • 連線選項 更多資料庫
  • 外掛程式集合 大量開源
  • 廉價的網站託管;
  • 與 HTML 的良好協同作用;
  • 優良的彈性和組合性;
  • 雲解決專案提供的各種好處。

現在,讓我們更仔細地回顧一下 PHP 列出的優點 ,以瞭解如何在實踐中應用它們來提高 Web 應用程式的質量、功能和盈利能力。

為什麼使用 PHP? 主要優點和缺點

1. 大量可用專家可供選取

PHP 的流行催生了眾多的開發人員社區,其中一小部分可能是潛在的招聘候選人。 大量可用的專家導致高競爭力和較低的薪資要求,這有利於降低開發成本。 此外,這種語系非常容易學習和實現,因此即使是初級開發人員通常也能夠有效地實現應用程式的基本功能。

2. 豐富的文件

有很多教學、手冊和其他參考資料可供使用,這有助於開發,並可以在困難的情況下提供幫助和靈感來源。 這些材料對於新手程式員來說也是非常寶貴的,隨著難度的逐漸增加,學習過程變得更加容易。 而且,如上所述,學習 PHP 相對容易,儘管不像學習 Python 那樣容易,這進一步增加了它的受歡迎程度。

3. 提高加載速度

與許多其他 Web 開發技術相比,PHP 的使用使網站頁面加載速度更快。 例如,目前,在大多數使用場景中,PHP 的速度大約是 Python 的三倍。 反過來,較低的加載時間是一個重要的 SEO 排名因素,可以通過帶來競爭優勢來幫助進一步推廣網站。 更高的應用速度可以讓客戶滿意,並與其他優勢相結合,有助於建立和保留客戶群。

4. 廣泛的資料庫選取

PHP 容許連線到幾乎任何類型的資料庫。 最常見的選取是MySQL,主要是因為它免費、有效且深受開發人員歡迎。 與 PHP 相容的資料庫管理系統的其他可靠選項有 mSQL、MS-SQL、SQLite、PostgreSQL 等。此外,PHP 同樣可以與 ElasticSearch、Redis、MongoDB 和其他非關係資料庫一起使用。 這樣,開發人員就不再局限於使用特定的資料庫,並且可以在考慮所有關聯因素的情況下為未來的應用程式選取最佳的資料庫。

5. 廉價的開源軟體

PHP 是一種免費使用的技術,可以節省大量的開發預算。 另外,通常與PHP結合使用的開發工具大多數都是開源軟體,可以免費使用; 因此,它們還降低了項目成本。 此外,還有許多框架(例如 Laravel 和 CodeIgniter)以及各種 CMS(例如 WordPress 和 Drupal)擴展了 PHP 的功能,使開發過程變得更輕鬆、更有效。

6.更便宜的託管服務

PHP網站最常見的運行場景是LAMP堆疊。 意味著網站運行在部署在Linux系統上的Apache HTTP Web伺服器 上,並使用MySQL作為資料庫。 所有這些元件都是免費的,並且堆疊經由充分測試,這意味著開發所需的時間和資金減少。

7. 與HTML優秀的結合性

PHP 提供內嵌式 HTML 寫程式,這就是這兩種技術之間令人難以置信的協同作用的原因。 在大多數情況下, PHP 腳本 不會干擾網頁的 HTML 代碼,而是在保持在 <?php ?> 旗標定義的邊框內的同時完成網頁的 HTML 代碼。 反之亦然,如果您在 PHP 上構建了整個頁面,則可以使用腳本整合 HTML 代碼。 在這種情況下,與傳統 HTML 頁面的區別在於開始標籤的順序相反:PHP 標籤位於 HTML 標籤之前。

8、柔韌性好

彈性使得PHP能夠與許多其他寫程式語系有效地結合,從而使軟體產品能夠針對每個特定功能使用最有效的技術。 此外,PHP 是一種跨平台語系,這意味著開發人員可以使用任何主要操作系統(Windows、Linux、macOS)來執行編碼。 這種彈性使開發過程變得更快、成本更低,從而極大地促進了開發過程。

9. 與雲服務的相容性

如今,許多現代產品傾向於使用 Amazon Web Services 等雲計算解決專案來實現各種目的。 用 PHP 編寫的應用程式由不同的雲服務支援,例如 AWS Lambda。 這樣,PHP應用程式就可以部署在雲伺服器上,並達到良好的擴展性等有益效果。 更重要的是,雲計算領域並沒有被其他編碼語系所壟斷,因此 PHP 在此類實現中佔據了一席之地。

 

PHP近期和遙遠 的未來

目前,PHP 仍然處於 Web 開發世界的頂端。 所有網站中很大一部分都使用這種寫程式語系運行,並且易於使用的 CMS WordPress 繼續受到歡迎。 它容許使用者只需點選幾下即可在免費或付費託管平台上設計和部署自己的網站。 這就是為什麼 PHP 語系的不久的將來看起來是光明的,因為它將繼續發展並被廣泛使用。

然而,PHP 的遙遠前景引起了人們對其未來在 Web 開發中的可行性的擔憂。 例如,Python 已經比 PHP 吸引了更多的新開發人員,而且這種趨勢不太可能很快改變。 此外,由於存在專門的庫,Python 在處理一些高要求的功能(例如機器學習)方面比 PHP 更好。 按照這個速度,PHP 需要在其發展中實現重大飛躍才能趕上 Python,否則它的受歡迎程度將繼續下降。

結論

考慮到所有利弊,可以最終確定商業利益並回答邏輯問題“為什麼使用 PHP?”

  1. 它廣泛流行,因此您一定會找到適合您需求的開發團隊。
  2. 它相當簡單且文件齊全,因此開發過程可能會花費更少的時間。
  3. 它非常靈活,並且與其他 Web 開發技術結合得很好,因此開發團隊將擁有更多可用的工具。
  4. 它是一種開源技術,可以降低構建、部署和維護應用程式所需的成本。
  5. 它比其他 Web 開發技術(例如 Python)更快,尤其是在用於簡單應用程式時。

 

 

PHP程式設計問題諮詢:
要如何使Html/PHP格式的字串不被解釋,而是照原樣顯示?

———————————————————
PHP程式設計問題回覆:
使Html/PHP格式的字串不被解釋,你可以這樣處理:

<?PHP
$str=”<h1>PHP</h1>”;
Echo “被解釋過的: “.$str.”<br>經過處理的:”;
Echo  htmlentities(nl2br($str));
?>
———————————————————

常用的php正則表達式及語法註解:

符合中文字元的正則表達式: [u4e00-u9fa5]
註解:符合中文還真是個頭疼的事,有了這個表達式就好辦了

符合雙位元組字元(內含中文字在內):[^x00-xff]
註解:可以用來計算字串的長度(一個雙位元組字元長度計2,ASCII字元計1)

符合空白行的正則表達式:
s*

註解:可以用來刪除空白行

符合 HTML標示的正則表達式:<(S*?)[^>]*>.*?|<.*? />
註解:網上流傳的版本太糟糕,上面這個也僅僅能符合部分,對於複雜的嵌套標示依舊無能為力

符合首尾空白字元的正則表達式:^s*|s*$
註解:可以用來刪除行首行尾的空白字元(內含空格、製表符、換頁符等等),非常有用的表達式

符合Email位址的正則表達式:w+ ([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
註解:表單驗證時很實用

符合網址URL的正則表達式:[a-zA-z]+://[^s]*
註解:網上流傳的版本功能很有限,上面這個基本可以滿足需求

符合帳號是否合法 (字母開頭,容許5-16位元組,容許字母數字下劃線):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
註解:表單驗證時很實用

符合電話號碼:d{3}-d{8}|d{4}-d{7}
註解:符合形式如 0511-4405222 或 021-87888822

符合騰訊QQ號:[1-9][0-9]{4,}
註解:騰訊QQ號從10000開始

符合中國郵政編碼:[1-9]d{5}(?! d)
註解:中國郵政編碼為6位數字

符合身份證:d{15}|d{18}
註解:中國的身份證為15位或18位

符合ip位址:d+.d+.d+.d+
註解:提取ip位址時有用

符合特定數字:
^[1-9]d*$    //符合正整數
^-[1-9]d*$   //符合負整數
^-?[1-9]d*$   //符合整數
^[1-9]d*|0$   //符合非負整數(正整數 + 0)
^-[1-9]d*|0$   //符合非正整數(負整數 + 0)
^[1-9]d*.d*|0.d*[1-9]d*$    //符合正浮點數
^-([1-9]d*.d*|0.d*[1-9]d*)$  //符合負浮點數
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$   //符合浮點數
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$   //符合非負浮點數(正浮點數 + 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$  //符合非正浮點數(負浮點數 + 0)
註解:處理大量資料時有用,具體應用時注意修正

符合特定字串:
^[A-Za-z]+$  //符合由26個英文字母組成的字串
^[A-Z]+$   //符合由26個英文字母的大寫組成的字串
^[a-z]+$  //符合由26個英文字母的小寫組成的字串
^[A-Za-z0-9]+$   //符合由數字和26個英文字母組成的字串
^w+$  //符合由數字、26個英文字母或是下劃線組成的字串
註解:最基本也是最常用的一些表達式

解決:執行程式發生記憶體不足解決方法 Fatal error

網頁開啟後出現這樣的字串:Fatal error: Allowed memory size of 16789338 bytes exhausted

這是因為:php 執行程式發生記憶體不足解決方法 Fatal error: Allowed memory size of 16789338 bytes exhausted
在php.ini 文件裡把memory_limit = 16M這個數值調大,例如修改成32M或更大。

今天總教頭在此提供一個更好的解決方法,只要直接在php程式中設定
(當然:記憶體大小可視需求,記得要放在整個程式的前面)就可以了

<?php

ini_set(‘memory_limit’,’128m’);

?>

這個方法是在php程式上動態設定memory,不會動到PHP的全域變數設定。
馬上可以解決執行程式發生記憶體不足解決方法 Fatal error……………

類建立好了..
那麼類肯定不止這些東西,它由繼承,屬性,返回值等.

1.方法的參數.
有方法,該方法就可能要有參數.參數是如何傳遞過來的呢?
如果看過之前的文章.那麼你肯定就知道了..是的 與普通函數的參數相同.
聲明char類型的指標用來儲存參數的值.
聲明int類型的變量來儲存的參數長度
然後用到 zend_parse_parameters函數
zend_parse_parameters(“,`< char *type_spec>`,`< …>`)
該參數有幾個重要的參數
第一個是參數的個數
第二個比較重要,它指定接收參數的類型
下面這份清單完整地列舉出了我們可以指定接收的參數類型:

l – 長整數

d – 雙精度浮點數

s – 字串 (也可能是空位元組)和其長度

b – 布林值

r – 資源, 儲存在 zval*

a – 陣列, 儲存在 zval*

o – (任何類的)對像, 儲存在 zval*

O – (由class entry 特殊的類的)對像, 儲存在 zval*

z – 實際的 zval*

下面的一些字元在類型說明字串(就是那個 char *type_spec)中具有特別的含義:

| – 顯示剩下的參數都是可選參數。如果使用者沒有傳進來這些參數值,那麼這些值就會被起始化成預設值。

/ – 顯示參數解析函數將會對剩下的參數以 SEPARATE_ZVAL_IF_NOT_REF() 的模式來提供這個參數的一份覆制,除非這些參數是一個引用。

! – 顯示剩下的參數容許被設定為 NULL(僅用在 a、o、O、r和z身上)。如果使用者傳進來了一個 NULL 值,則存儲該參數的變量將會設定為 NULL。
函數 get接收兩個參數 ,第一個參數是必填字串類型,第二個參數是可選為整型.
PHP代碼如下
1
2
3
    
function get($name,$age=0){
 
}

如果要在延伸裡實現這樣的功能,zend_parse_parameters的使用如下
char* name;
int name_length;
int age;
int age_length;
zend_parse_parameters(ZEND_NUM_ARGS ,」s|l」,&name,&name_length,&age,&age_len)
zend_parse_parameters 執行失敗的話會返回FAILURE.
執行完成後,name就是第一個參數的值,age就是第二個參數的值
我們甚至可以呼叫php_printf函數來輸出.

2.類的屬性
這類的內容在上一篇文章中其實已經講清楚了.
用zend_declare_property_*一系列函數來建立我們的屬性.當然是在PHP_MINIT_FUNCTION函數中建立
以 zend_declare_property_null為例:
zend_declare_property_null(“,`< char *name>`,`< int name_length>`,`< int access_type TSRMLS_DC>`)
ce :是一個zend_class_entry的指標.
name :是屬性的名稱
length :屬性名稱的長度
access_type:屬性的訪問層級.
還有其他幾個函數 用法一樣.
1
2
3
4
5
6
7
    
zend_declare_property_bool
zend_declare_property_double
zend_declare_property_ex
zend_declare_property_long
zend_declare_property_null
zend_declare_property_string
zend_declare_property_stringl

3.讀取屬性
建立了屬性,那麼該如何讀取此屬性呢?
zend_read_property(“,`< zval *object>`,`< char *name>`,`< int name_length>`,`< zend_bool silent TSRMLS_DC>`);
就要使用這個函數了,它將取得到的屬性訊息返回到一個zval結構體中
這時候要用到函數getThis();
這個函數會返回一個zval的指標.
因為是一個對像 所以儲存在結構體_zend_object_value 中
typedef struct _zend_object_value {
zend_object_handle handle;
zend_object_handlers *handlers;
} zend_object_value;
第一個參數會呼叫 zend_object_handler所指向的函數指標get_class_entry來取得現用的執行的類的訊息.
第一個參數應該是 Z_OBJEC_P(getThis());
第二個參數是 getThis();
它定義為 #define getThis() (this_ptr);
this_ptr是什麼東西我還不確定,我想應該是PHP內核維護的一個儲存類訊息的zval對像.回頭再好好研究研究.
第三個參數是要取得的屬性
第四個參數是屬性的長度.
修改之後的getproperty方法
1
2
3
4
5
6
    
PHP_METHOD(Person,getproperty){
        zval* self=getThis();
        zval* name;
        name=zend_read_property(Z_OBJCE_P(self),self,ZEND_STRL("name"),0 TSRMLS_CC);
        php_printf("%s",name->value.str.val);
}

4.設定屬性
該如何更新屬性的值呢?
同樣給我們提供了一個函數
zend_update_property(“,`< zval *object>`,`< char *name>`,`< int name_length>`,`< zval *value TSRMLS_DC>`)
前四個參數與zend_read_property相同.
不同的是最後一個zval*value.它是我們屬性的值..因為他是一個zval的指標,所以我們需要將通過zend_parse_parameters取得到的參數轉為一個zval的指標.
修改後的setproperty方法.
1
2
3
4
5
6
7
8
9
10
11
12
13
    
PHP_METHOD(Person,setproperty){
        char *key=NULL;
        int key_len;
        char *val=NULL;
        int val_len;
        zval* self=getThis();
        zval* value;
        if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"ss",&key,&key_len,&val,&val_len)==FAILURE){
                return;
        }
        MAKE_STD_ZVAL(value);
        ZVAL_STRINGL(value,val,val_len,1);
        zend_update_property(Z_OBJCE_P(self),self,key,key_len,value TSRMLS_CC);

最後make && make install,重啟apache.
這樣我們在 php代碼裡.
1
2
3
4
5
    
<?php
$a=new Person();
$a->setproperty("name","this is siren");
$a->getproperty();
?>

就可以輸出我們通過setproperty設定的值了.

聲明:本文為斯人原創,全部為作者一一分析得之,有不對的地方望賜教。
歡迎轉載,轉載請註明出處 。
本文位址:http://imsiren.com/archives/581

PHP程式設計問題諮詢:
如何比較兩個日期相差幾天?

———————————————————
PHP程式設計問題回覆:
要如何比較兩個日期相差幾天,請看以下的範例:

<?PHP
$Date_1="2003-7-15";//也可以是:$Date_1="2003-6-25 23:29:14";
$Date_2="1982-10-1";
$Date_List_1=explode("-",$Date_1);
$Date_List_2=explode("-",$Date_2);
$d1=mktime(0,0,0,$Date_List_1[1],$Date_List_1[2],$Date_List_1[0]);
$d2=mktime(0,0,0,$Date_List_2[1],$Date_List_2[2],$Date_List_2[0]);
$Days=round(($d1-$d2)/3600/24);
Echo   "我已經奮鬥了 $Days 天^_^";
?>

———————————————————

PHP網站如何防止CC攻擊呢?

所謂的CC攻擊就是對方利用程式或一些代理對您的網站進行不間斷的訪問,造成您的網站處理不了而處於當機狀態。
這種時候您的統計系統(可能是量子、百度等)當然也是統計不到的。
不過我們可以借助於一些防攻擊的軟體來實現,不過效果有時並不明顯。
下面我提供一段PHP的代碼,可以起到一定的防CC效果。

 

主要功能:在3秒內連續重整頁面5次以上將指向本機 http://127.0.0.1

在PHP網站開發中為了網站推廣和SEO等需要,需要對網站進行全站或局部靜態化處理,PHP生成靜態HTML頁面有多種方法
例如:利用PHP範本、快取等實現頁面靜態化
今天就以PHP案例教學形式討論PHP生成靜態頁面的方法。
頁面靜態化的方法,分為兩種
一種是偽靜態,就是url 重寫
一種是你真的靜態化。

下面介紹PHP中頁面靜態化的方法。

什麼是PHP程式網頁靜態化?
PHP程式網頁靜態化的簡單理解就是使網站生成頁面以靜態HTML的形式展現在訪客面前
PHP靜態化分純靜態化和偽靜態化,兩者的區別在於PHP生成靜態頁面的處理機制不同。

 

PHP程式網頁生成靜態HTML頁面的方法:
1、利用PHP範本生成靜態頁面
PHP範本實現靜態化非常方便,比如安裝和使用PHP Smarty實現網站靜態化。

2、使用PHP檔案讀寫功能生成靜態頁面
PHP生成靜態頁面案例代碼

<?
$out1 = “<html><head><title>PHP程式網頁靜態化教學</title></head>
<body>歡迎訪問PHP網站開發教學網http://por.tw,本文主要介紹PHP網站頁面靜態化的方法
</body></html>”;
$fp = fopen(“leapsoulcn.html”,”w”);
if(!$fp)
{
echo “System Error”;
exit();
}
else {
fwrite($fp,$out1);
fclose($fp);
echo “Success”;
}
?>
———————————————————————–
    3、使用PHP輸出控制函數(Output Control)生成靜態頁面

    輸出控制函數(Output Control)也就是使用和控制快取來生成靜態HTML頁面,也會使用到PHP檔案讀寫函數。

    PHP生成靜態頁面案例代碼

———————————————————————–
<?
ob_start();
echo “<html>”.
“<head>”.
“<title>PHP網站靜態化教學</title>”.
“</head>”.
“<body>歡迎訪問PHP網站開發教學網http://por.tw,本文主要介紹PHP網站頁面靜態化的方法</body>”.
“</html>”;
$out1 = ob_get_contents();
ob_end_clean();
$fp = fopen(“leapsoulcn.html”,”w”);
if(!$fp)
{
echo “System Error”;
exit();
}
else
{
fwrite($fp,$out1);
fclose($fp);
echo “Success”;
}
?>
———————————————————————
我們知道使用PHP進行網站開發,一般執行結果直接輸出到遊覽器,為了使用PHP生成靜態頁面,就需要使用輸出控制函數控制快取區,以便取得快取區的內容,然後再輸出到靜態HTML頁面檔案中以實現網站靜態化。

PHP生成靜態頁面的思路為:
首先開啟快取,然後輸出了HTML內容(你也可以通過include將HTML內容以檔案形式包括進來),之後取得快取中的內容,清理快取後通過PHP檔案讀寫函數將快取內容寫入到靜態HTML頁面檔案中。

獲得輸出的快取內容以生成靜態HTML頁面的過程需要使用三個函數:
ob_start()、ob_get_contents()、ob_end_clean()。

   PHP程式網頁生成靜態頁面知識:

   1、ob_start函數一般主要是用來開啟快取,注意使用ob_start之前不能有任何輸出,如空格、字元等。

        2、ob_get_contents函數主要用來取得快取中的內容以字串形式返回,注意此函數必須在ob_end_clean函數之前呼叫,否則取得不到快取內容。

        3、ob_end_clean函數主要是清理快取中的內容並關閉快取,完成則返回True,失敗則返回False

PHP輸出控制函數(Output Control)有很多應用。

至此,使用PHP生成靜態HTML頁面以實現網站靜態化的方法就介紹完了,根據實際情況和需求你可以選取不同的靜態化方法。

[PHP] include_once 與 require_once(包含其它的檔案進來)

include_once 與 require_once都是PHP的函式,主要是要包含其它的檔案進來,而且萬一該檔案被包含過了,則不會重新再包含一次。

而基於PHP不可能開發同一個函式的情況下,去試了一下他的不同之處,在於include_once萬一遇到錯誤,則會持續執行。
但require_once則會停止執行,並產生Fatal Errors。

以程式碼說明如下:

檔名:test.php

<?php
 require_once("a.php");
 require_once("c.php");
 echo dirname(__FILE__)." in test.php ";
?>

檔名:a.php

<?php
 echo dirname(__FILE__)." in a.php"."</br>";
 require_once("b.php");
?>

檔名:b.php

<?php
 echo dirname(__FILE__)." in b.php"."</br>";
?>

則會出現下列結果:
C:AppServwwwPTS in a test.php
C:AppServwwwPTS in b test.php

Warning: require_once(c.php) [function.require-once]: failed to open stream: No such file or directory in C:AppServwwwPTS est.php on line 3

Fatal error: require_once() [function.require]: Failed opening required 'c.php' (include_path='.;C:php5pear') in C:AppServwwwPTS est.php on line 3
但若是改成include_once,則會變成
C:AppServwwwPTS in a test.php
C:AppServwwwPTS in b test.php

Warning: require_once(c.php) [function.require-once]: failed to open stream: No such file or directory in C:AppServwwwPTS est.php on line 3

Warning: include_once() [function.include]: Failed opening 'c.php' for inclusion (include_path='.;C:php5pear') in C:AppServwwwPTS est.php on line 3
C:AppServwwwPTS in test.php
由此應該可以很輕易地看出兩者的不同了!

您知道最短的PHP微網誌程式代碼如何編寫嗎?

最短的PHP微網誌程式。
基本需求是:
1.無亂碼(最好UTF-8)。
2.有輸入框可以發佈新訊息。
3.送出後馬上可以看到新發的內容。
4.必須使用POST模式送出。
5.訊息後面要有時間標示。
6.不能發佈任何HTML標籤。

<?php
header("content-type:text/html; charset=utf-8");
$a=@file_get_contents(l);
($p=$_POST[s])&&file_put_contents(l,$a='<hr>'.htmlspecialchars($p).date(' Y-m-d H:i').$a);
echo '<form method=post><input name=s></form>'.$a;
?>

運行效果如圖:

註釋一下:

<?php
header("content-type:text/html; charset=utf-8"); //傳送到utf-8聲明
/*
* 從名叫l的檔案裡面讀取資料。
* php裡面的常量如果沒有先聲明,那麼預設值是等於常量本身的那個字串。
* 也就是說沒有聲明過的l=="l" , ABCD == "ABCD"
*/
$a=@file_get_contents(l);
/*
* a && b; 貌似是php特有的語法結構。 大概意思是 先執行a,
* 然後判斷a是否為true,如果是,那麼繼續執行b
*
* ($p=$_POST[s]) 是先把$_POST[s]的值賦給$p,
* 然後括號的值為$p轉換為布爾型。也就是說,只要$p不是空字串,
* 或是false,或是0,或是null。就會繼續執行後面的語句
*
* 後面操作是把剛剛讀出來的$a的前面加上新的資料,然後寫入l檔案
*/
($p=$_POST[s])&&file_put_contents(l,$a='<hr>'.htmlspecialchars($p).date(' Y-m-d H:i').$a);
/*
* 顯示html語句,用於構造一個可以post送出的輸入框,沒有送出按鈕,直接按換行送出。
* 由於頁面是用utf-8編碼,所以送出的資料也是utf-8編碼
*/
echo '<form method=post><input name=s></form>'.$a;//#註釋2
?>

正則表達式是一個無比強大的工具.任何地方我們都可能用到它…
原來刻苦的啃過 正則表達式,但時間長了還是會忘…
今天又來溫習一下..看到一篇不錯的文章..所以就轉過來收藏下.

前言:
半年前我對正則表達式產生了興趣,在網上尋找過不少資料,看過不少的教學,最後在使用一個正則表達式工具RegexBuddy時發現他的教學寫的非常好,可以說是我目前見過最好的正則表達式教學。於是一直想把他翻譯過來。這個願望直到這個五一長假才得以實現,結果就有了這篇文章。關於本文的名字,使用「深入淺出」似乎已經太俗。但是通讀原文以後,覺得只有用「深入淺出」才能準確的表達出該教學給我的感受,所以也就不能免俗了。
本文是Jan Goyvaerts為RegexBuddy寫的教學的譯文,版權歸原作者所有,歡迎轉載。但是為了尊重原作者和譯者的勞動,請註明出處!謝謝!

1.什麼是正則表達式

基本說來,正則表達式是一種用來描述一定數量文字的模式。Regex代表Regular Express。本文將用<<regex>>來表示一段具體的正則表達式。

一段文字就是最基本的模式,簡單的符合相同的文字。

2.不同的正則表達式引擎

正則表達式引擎是一種可以處理正則表達式的軟體。通常,引擎是更大的應用程式的一部分。在軟體世界,不同的正則表達式並不互相相容。本教學會集中討論Perl 5 類型的引擎,因為這種引擎是應用最廣泛的引擎。同時我們也會提到一些和其他引擎的區別。許多近代的引擎都很類似,但不完全一樣。例如.NET正則庫,JDK正則包。

3.文字元號

最基本的正則表達式由單個文字元號組成。如<<a>>,它將符合字串中第一次出現的字元「a」。如對字串「Jack is a boy」。「J」後的「a」將被符合。而第二個「a」將不會被符合。

正則表達式也可以符合第二個「a」,這必須是你告訴正則表達式引擎從第一次符合的地方開始搜尋。在文字編輯器中,你可以使用「尋找下一個」。在寫程式語系中,會有一個函數可以使你從前一次符合的位置開始繼續向後搜尋。

類似的,<<cat>>會符合「About cats and dogs」中的「cat」。這等於是告訴正則表達式引擎,找到一個<<c>>,緊跟一個<<a>>,再跟一個<<t>>。

要注意,正則表達式引擎預設是大小寫敏感的。除非你告訴引擎忽略大小寫,否則<<cat>>不會符合「Cat」。

    特殊字元

對於文字字元,有12個字元被保留作特殊用途。他們是:

[ ] ^ $ . | ? * + ( )

這些特殊字元也被稱作元字元。

如果你想在正則表達式中將這些字元用作文字字元,你需要用反斜槓「」對其進行換碼 (escape)。例如你想符合「1+1=2」,正確的表達式為<<1+1=2>>.

需要注意的是,<<1+1=2>>也是有效的正則表達式。但它不會符合「1+1=2」,而會符合「123+111=234」中的「111=2」。因為「+」在這裡表示特殊含義(重複1次到多次)。

在寫程式語系中,要注意,一些特殊的字元會先被編譯器處理,然後再傳遞給正則引擎。因此正則表達式<<1+2=2>>在C++中要寫成「1+1=2」。為了符合「C: emp」,你要用正則表達式<<C: emp>>。而在C++中,正則表達式則變成了「C: emp」。

    不可顯示字元

可以使用特殊字元序列來代表某些不可顯示字元:

<< >>代表Tab(0×09)

<<
>>代表換行符(0x0D)

<<
>>代表換行符(0x0A)

要注意的是Windows中文字檔案使用「
」來結束一行而Unix使用「
」。

4.正則表達式引擎的內定工作機制

知道正則表達式引擎是如何工作的有助於你很快理解為何某個正則表達式不像你期望的那樣工作。

有兩種類型的引擎:文字導向(text-directed)的引擎和正則導向(regex-directed)的引擎。Jeffrey Friedl把他們稱作DFA和NFA引擎。本文談到的是正則導向的引擎。這是因為一些非常有用的特性,如「惰性」量詞(lazy quantifiers)和反向引用(backreferences),只能在正則導向的引擎中實現。所以毫不意外這種引擎是目前最流行的引擎。

你可以輕易分辨出所使用的引擎是文字導向還是正則導向。如果反向引用或「惰性」量詞被實現,則可以肯定你使用的引擎是正則導向的。你可以作如下測試:將正則表達式<<regex|regex not>>應用到字串「regex not」。如果符合的結果是regex,則引擎是正則導向的。如果結果是regex not,則是文字導向的。因為正則導向的引擎是「猴急」的,它會很急切的進行表功,報告它找到的第一個符合 。

    正則導向的引擎總是返回最左邊的符合

這是需要你理解的很重要的一點:即使以後有可能發現一個「更好」的符合,正則導向的引擎也總是返回最左邊的符合。

當把<<cat>>應用到「He captured a catfish for his cat」,引擎先比較<<c>>和「H」,結果失敗了。於是引擎再比較<<c>>和「e」,也失敗了。直到第四個字元,<<c>>符合了「c」。<<a>>符合了第五個字元。到第六個字元<<t>>沒能符合「p」,也失敗了。引擎再繼續從第五個字元重新檢查符合性。直到第十五個字元開始,<<cat>>符合上了「catfish」中的「cat」,正則表達式引擎急切的返回第一個符合的結果,而不會再繼續尋找是否有其他更好的符合。

5.字集

字集是由一對方括號「[]」括起來的字集合。使用字集,你可以告訴正則表達式引擎僅僅符合多個字元中的一個。如果你想符合一個「a」或一個「e」,使用<<[ae]>>。你可以使用<<gr[ae]y>>符合gray或grey。這在你不確定你要搜尋的字元是採用美國英語還是英國英語時特別有用。相反,<<gr[ae]y>>將不會符合graay或graey。字集中的字元順序並沒有什麼關係,結果都是相同的。

你可以使用連字元「-」定義一個字元範圍作為字集。<<[0-9]>>符合0到9之間的單個數字。你可以使用不止一個範圍。<<[0-9a-fA-F] >>符合單個的十六進位數字,並且大小寫不敏感。你也可以結合範圍定義與單個字元定義。<<[0-9a-fxA-FX]>>符合一個十六進位數字或字母X。再次強調一下,字元和範圍定義的先後順序對結果沒有影響。

    字集的一些應用

尋找一個可能有拼字錯誤的單詞,比如<<sep[ae]r[ae]te>> 或 <<li[cs]en[cs]e>>。

尋找程式語系的標識符,<<A-Za-z_][A-Za-z_0-9]*>>。(*表示重複0或多次)

尋找C風格的十六進位數<<0[xX][A-Fa-f0-9]+>>。(+表示重複一次或多次)

    取反字集

在左方括號「[」後面緊跟一個尖括號「^」,將會對字集取反。結果是字集將符合任何不在方括號中的字元。不像「.」,取反字集是可以符合換行換行符的。

需要記住的很重要的一點是,取反字集必須要符合一個字元。<<q[^u]>>並不意味著:符合一個q,後面沒有u跟著。它意味著:符合一個q,後面跟著一個不是u的字元。所以它不會符合「Iraq」中的q,而會符合「Iraq is a country」中的q和一個空格符。事實上,空格符是符合中的一部分,因為它是一個「不是u的字元」。

如果你只想符合一個q,條件是q後面有一個不是u的字元,我們可以用後面將講到的向前檢視來解決。

    字集中的元字元

需要注意的是,在字集中只有4個 字元具有特殊含義。它們是:「] ^ -」。「]」代表字集定義的結束;「」代表轉義;「^」代表取反;「-」代表範圍定義。其他常見的元字元在字集定義內定都是標準字元,不需要轉義。例如,要搜尋星號*或加號+,你可以用<<[+*]>>。當然,如果你對那些通常的元字元進行轉義,你的正則表達式一樣會工作得很好,但是這會降低可讀性。

在字集定義中為了將反斜槓「」作為一個文字字元而非特殊含義的字元,你需要用另一個反斜槓對它進行轉義。<<[x]>>將會符合一個反斜槓和一個X。「]^-」都可以用反斜槓進行轉義,或是將他們放在一個不可能使用到他們特殊含義的位置。我們推薦後者,因為這樣可以增加可讀性。比如對於字元「^」,將它放在除了左括號「[」後面的位置,使用的都是文字字元含義而非取反含義。如<<[x^]>>會符合一個x或^。<<[]x]>>會符合一個「]」或「x」。<<[-x]>>或<<[x-]>>都會符合一個「-」或「x」。

    字集的簡寫

因為一些字集非常常用,所以有一些簡寫模式。

<<d>>代表<<[0-9]>>;

<<w>>代表單詞字元。這個是隨正則表達式實現的不同而有些差異。絕大多數的正則表達式實現的單詞字集都包括了<<A-Za-z0-9_]>>。

<<s>>代表「白字元」。這個也是和不同的實現有關的。在絕大多數的實現中,都包括了空格符和Tab符,以及換行換行符<<
>>。

字集的縮寫形式可以用在方括號之內或之外。<<sd>>符合一個白字元後面緊跟一個數字。<<[sd]>>符合單個白字元或數字。<<[da-fA-F]>>將符合一個十六進位數字。

取反字集的簡寫

<<[S]>> = <<[^s]>>

<<[W]>> = <<[^w]>>

<<[D]>> = <<[^d]>>

    字集的重複

如果你用「?*+」操作符來重複一個字集,你將會重複整個字集。而不僅是它符合的那個字元。正則表達式<<[0-9]+>>會符合837以及222。

如果你僅僅想重複被符合的那個字元,可以用向後引用達到目的。我們以後將講到向後引用。

6.使用?*或+ 進行重複

?:告訴引擎符合前導字元0次或一次。事實上是表示前導字元是可選的。

+:告訴引擎符合前導字元1次或多次

*:告訴引擎符合前導字元0次或多次

<[A-Za-z][A-Za-z0-9]*>符合沒有屬性的HTML標籤,「<」以及「>」是文字元號。第一個字集符合一個字母,第二個字集符合一個字母或數字。

我們似乎也可以用<[A-Za-z0-9]+>。但是它會符合<1>。但是這個正則表達式在你知道你要搜尋的字串不包括類似的無效標籤時還是足夠有效的。

    限制性重複

許多現代的正則表達式實現,都容許你定義對一個字元重複多少次。詞法是:{min,max}。min和max都是非負整數。如果逗號有而max被忽略了,則max沒有限制。如果逗號和max都被忽略了,則重複min次。

因此{0,}和*一樣,{1,}和+ 的作用一樣。

你可以用<<[1-9][0-9]{3}>>符合1000~9999之間的數字(「」表示單詞邊界)。<<[1-9][0-9]{2,4}>>符合一個在100~99999之間的數字。

    注意貪婪性

假設你想用一個正則表達式符合一個HTML標籤。你知道輸入將會是一個有效的HTML檔案,因此正則表達式不需要排除那些無效的標籤。所以如果是在兩個尖括號之間的內容,就應該是一個HTML標籤。

許多正則表達式的新手會首先想到用正則表達式<< <.+> >>,他們會很驚訝的發現,對於測試字串,「This is a <EM>first</EM> test」,你可能期望會返回<EM>,然後繼續進行符合的時候,返回</EM>。

但事實是不會。正則表達式將會符合「<EM>first</EM>」。很顯然這不是我們想要的結果。原因在於「+」是貪婪的。也就是說,「+」會導致正則表達式引擎試圖盡可能的重複前導字元。只有當這種重複會引起整個正則表達式符合失敗的情況下,引擎會進行回溯。也就是說,它會放棄最後一次的「重複」,然後處理正則表達式餘下的部分。

和「+」類似,「?*」的重複也是貪婪的。

    深入正則表達式引擎內定

讓我們來看看正則引擎如何符合前面的例子。第一個記號是「<」,這是一個文字元號。第二個符號是「.」,符合了字元「E」,然後「+」一直可以符合其餘的字元,直到一行的結束。然後到了換行符,符合失敗(「.」不符合換行符)。於是引擎開始對下一個正則表達式符號進行符合。也即試圖符合「>」。到目前為止,「<.+」已經符合了「<EM>first</EM> test」。引擎會試圖將「>」與換行符進行符合,結果失敗了。於是引擎進行回溯。結果是現在「<.+」符合「<EM>first</EM> tes」。於是引擎將「>」與「t」進行符合。顯然還是會失敗。這個過程繼續,直到「<.+」符合「<EM>first</EM」,「>」與「>」符合。於是引擎找到了一個符合「<EM>first</EM>」。記住,正則導向的引擎是「急切的」,所以它會急著報告它找到的第一個符合。而不是繼續回溯,即使可能會有更好的符合,例如「<EM>」。所以我們可以看到,由於「+」的貪婪性,使得正則表達式引擎返回了一個最左邊的最長的符合。

    用懶惰性取代貪婪性

一個用於修正以上問題的可能專案是用「+」的惰性代替貪婪性。你可以在「+」後面緊跟一個問號「?」來達到這一點。「*」,「{}」和「?」表示的重複也可以用這個專案。因此在上面的例子中我們可以使用「<.+?>」。讓我們再來看看正則表達式引擎的處理過程。

再一次,正則表達式記號「<」會符合字串的第一個「<」。下一個正則記號是「.」。這次是一個懶惰的「+」來重複上一個字元。這告訴正則引擎,盡可能少的重複上一個字元。因此引擎符合「.」和字元「E」,然後用「>」符合「M」,結果失敗了。引擎會進行回溯,和上一個例子不同,因為是惰性重複,所以引擎是延伸惰性重複而不是減少,於是「<.+」現在被延伸為「<EM」。引擎繼續符合下一個記號「>」。這次得到了一個完成符合。引擎於是報告「<EM>」是一個完成的符合。整個過程大致如此。

    惰性延伸的一個替代專案

我們還有一個更好的替代專案。可以用一個貪婪重複與一個取反字集:「<[^>]+>」。之所以說這是一個更好的專案在於使用惰性重複時,引擎會在找到一個完成符合前對每一個字元進行回溯。而使用取反字集則不需要進行回溯。

最後要記住的是,本教學僅僅談到的是正則導向的引擎。文字導向的引擎是不回溯的。但是同時他們也不支援惰性重複操作。

7.使用「.」符合幾乎任意字元

在正則表達式中,「.」是最常用的符號之一。不幸的是,它也是最容易被誤用的符號之一。

「.」符合一個單個的字元而不用關心被符合的字元是什麼。唯一的例外是新行符。在本教學中談到的引擎,預設情況下都是不符合新行符的。因此在預設情況下,「.」等於是字集[^

](Window)或[^
]( Unix)的簡寫。

這個例外是因為歷史的原因。因為早期使用正則表達式的工具是基於行的。它們都是一行一行的讀入一個檔案,將正則表達式分別應用到每一行上去。在這些工具中,字串是不包括新行符的。因此「.」也就永遠不符合新行符。

現代的工具和語系能夠將正則表達式應用到很大的字串甚至整個檔案上去。本教學討論的所有正則表達式實現都提供一個選項,可以使「.」符合所有的字元,內含新行符。在RegexBuddy, EditPad Pro或PowerGREP等工具中,你可以簡單的選中「點號符合新行符」。在Perl中,「.」可以符合新行符的模式被稱作「單行模式」。很不幸,這是一個很容易混淆的名詞。因為還有所謂「多行模式」。多行模式只影響行首行尾的錨定(anchor),而單行模式只影響「.」。

其他語系和正則表達式庫也採用了Perl的術語定義。當在.NET Framework中使用正則表達式類時,你可以用類似下面的語句來啟動單行模式:Regex.Match(「string」,」regex」,RegexOptions.SingleLine)

    保守的使用點號「.」

點號可以說是最強大的元字元。它容許你偷懶:用一個點號,就能符合幾乎所有的字元。但是問題在於,它也常常會符合不該符合的字元。

我會以一個簡單的例子來說明。讓我們看看如何符合一個具有「mm/dd/yy」格式的日期,但是我們想容許使用者來選取分隔設定。很快能想到的一個專案是<<dd.dd.dd>>。看上去它能符合日期「02/12/03」。問題在於02512703也會被認為是一個有效的日期。

<<dd[-/.]dd[-/.]dd>>看上去是一個好一點的解決專案。記住點號在一個字集裡不是元字元。這個專案遠不夠完善,它會符合「99/99/99」。而<<[0-1]d[-/.][0-3]d[-/.]dd>>又更進一步。儘管他也會符合「19/39/99」。你想要你的正則表達式達到如何完美的程度取決於你想達到什麼樣的目的。如果你想校驗使用者輸入,則需要盡可能的完美。如果你只是想分析一個已知的源,並且我們知道沒有錯誤的資料,用一個比較好的正則表達式來符合你想要搜尋的字元就已經足夠。

 

8.字串開始和結束的錨定

錨定和一般的正則表達式符號不同,它不符合任何字元。相反,他們符合的是字元之前或之後的位置。「^」符合一行字串第一個字元前的位置。<<^a>>將會符合字串「abc」中的a。<<^b>>將不會符合「abc」中的任何字元。

類似的,$符合字串中最後一個字元的後面的位置。所以<<c$>>符合「abc」中的c。

    錨定的應用

在寫程式語系中校驗使用者輸入時,使用錨定是非常重要的。如果你想校驗使用者的輸入為整數,用<<^d+$>>。

使用者輸入中,常常會有多餘的前導空格或結束空格。你可以用<<^s*>>和<<s*$>>來符合前導空格或結束空格。

    使用「^」和「$」作為行的開始和結束錨定

如果你有一個包括了多行的字串。例如:「first line

second line」(其中

表示一個新行符)。常常需要對每行分別處理而不是整個字串。因此,幾乎所有的正則表達式引擎都提供一個選項,可以延伸這兩種錨定的含義。「^」可以符合字串的開始位置(在f之前),以及每一個新行符的後面位置(在

和s之間)。類似的,$會符合字串的結束位置(最後一個e之後),以及每個新行符的前面(在e與

之間)。

在.NET中,當你使用如下代碼時,將會定義錨定符合每一個新行符的前面和後面位置:Regex.Match(「string」, 「regex」, RegexOptions.Multiline)

應用:string str = Regex.Replace(Original, 「^」, 「> 「, RegexOptions.Multiline)–將會在每行的行首插入「> 」。

    絕對錨定

<<A>>只符合整個字串的開始位置,<<>>只符合整個字串的結束位置。即使你使用了「多行模式」,<<A>>和<<>>也永遠不符合新行符。

即使和$只符合字串的結束位置,仍然有一個例外的情況。如果字串以新行符結束,則和$將會符合新行符前面的位置,而不是整個字串的最後面。這個「改進」是由Perl引進的,然後被許多的正則表達式實現所遵循,內含Java,.NET等。如果應用<<^[a-z]+$>>到「joe
」,則符合結果是「joe」而不是「joe
」。

9.單詞邊界

元字元<<>>也是一種對位置進行符合的「錨」。這種符合是0長度符合。

有4種位置被認為是「單詞邊界」:

1)  在字串的第一個字元前的位置(如果字串的第一個字元是一個「單詞字元」)

2)  在字串的最後一個字元後的位置(如果字串的最後一個字元是一個「單詞字元」)

3)  在一個「單詞字元」和「非單詞字元」之間,其中「非單詞字元」緊跟在「單詞字元」之後

4)  在一個「非單詞字元」和「單詞字元」之間,其中「單詞字元」緊跟在「非單詞字元」後面

「單詞字元」是可以用「w」符合的字元,「非單詞字元」是可以用「W」符合的字元。在大多數的正則表達式實現中,「單詞字元」通常內含<<[a-zA-Z0-9_]>>。

例如:<<4>>能夠符合單個的4而不是一個更大數的一部分。這個正則表達式不會符合「44」中的4。

換種說法,幾乎可以說<<>>符合一個「字母數字序列」的開始和結束的位置。

「單詞邊界」的取反集為<<B>>,他要符合的位置是兩個「單詞字元」之間或是兩個「非單詞字元」之間的位置。

    深入正則表達式引擎內定

讓我們看看把正則表達式<<is>>應用到字串「This island is beautiful」。引擎先處理符號<<>>。因為是0長度 ,所以第一個字元T前面的位置會被考察。因為T是一個「單詞字元」,而它前面的字元是一個空字元(void),所以符合了單詞邊界。接著<<i>>和第一個字元「T」符合失敗。符合過程繼續進行,直到第五個空格符,和第四個字元「s」之間又符合了<<>>。然而空格符和<<i>>不符合。繼續向後,到了第六個字元「i」,和第五個空格字元之間符合了<<>>,然後<<is>>和第六、第七個字元都符合了。然而第八個字元和第二個「單詞邊界」不符合,所以符合又失敗了。到了第13個字元i,因為和前面一個空格符形成「單詞邊界」,同時<<is>>和「is」符合。引擎接著嘗試符合第二個<<>>。因為第15個空格符和「s」形成單詞邊界,所以符合完成。引擎「急著」返回完成符合的結果。

10.  選取符

正則表達式中「|」表示選取。你可以用選取符符合多個可能的正則表達式中的一個。

如果你想搜尋文字「cat」或「dog」,你可以用<<cat|dog>>。如果你想有更多的選取,你只要延伸清單<<cat|dog|mouse|fish>>。

選取符在正則表達式中具有最低的優先級,也就是說,它告訴引擎要麼符合選取符左邊的所有表達式,要麼符合右邊的所有表達式。你也可以用圓括號來限制選取符的作用範圍。如<<(cat|dog)>>,這樣告訴正則引擎把(cat|dog)當成一個正則表達式單位來處理。

    注意正則引擎的「急於表功」性

正則引擎是急切的,當它找到一個有效的符合時,它會停止搜尋。因此在一定條件下,選取符兩邊的表達式的順序對結果會有影響。假設你想用正則表達式搜尋一個寫程式語系的函數清單:Get,GetValue,Set或SetValue。一個明顯的解決專案是<<Get|GetValue|Set|SetValue>>。讓我們看看當搜尋SetValue時的結果。

因為<<Get>>和<<GetValue>>都失敗了,而<<Set>>符合完成。因為正則導向的引擎都是「急切」的,所以它會返回第一個完成的符合,就是「Set」,而不去繼續搜尋是否有其他更好的符合。

和我們期望的相反,正則表達式並沒有符合整個字串。有幾種可能的解決辦法。一是考慮到正則引擎的「急切」性,改變選項的順序,例如我們使用<<GetValue|Get|SetValue|Set>>,這樣我們就可以優先搜尋最長的符合。我們也可以把四個選項結合起來成兩個選項:<<Get(Value)?|Set(Value)?>>。因為問號重複符是貪婪的,所以SetValue總會在Set之前被符合。

一個更好的專案是使用單詞邊界:<<(Get|GetValue|Set|SetValue)>>或<<(Get(Value)?|Set(Value)?>>。更進一步,既然所有的選取都有相同的結尾,我們可以把正則表達式改善為<<(Get|Set)(Value)?>>。

11.  組與向後引用

把正則表達式的一部分放在圓括號內,你可以將它們形成組。然後你可以對整個組使用一些正則操作,例如重複操作符。

要注意的是,只有圓括號「()」才能用於形成組。「[]」用於定義字集。「{}」用於定義重複操作。

當用「()」定義了一個正則表達式組後,正則引擎則會把被符合的組按照順序編號,存入快取。當對被符合的組進行向後引用的時候,可以用「數字」的模式進行引用。<<1>>引用第一個符合的後向引用組,<<2>>引用第二個組,以此類推,<<
>>引用第n個組。而<< >>則引用整個被符合的正則表達式本身。我們看一個例子。

假設你想符合一個HTML標籤的開始標籤和結束標籤,以及標籤中間的文字。比如<B>This is a test</B>,我們要符合<B>和</B>以及中間的文字。我們可以用如下正則表達式:「<([A-Z][A-Z0-9]*)[^>]*>.*?</1>」

首先,「<」將會符合「<B>」的第一個字元「<」。然後[A-Z]符合B,[A-Z0-9]*將會符合0到多次字母數字,後面緊接著0到多個非「>」的字元。最後正則表達式的「>」將會符合「<B>」的「>」。接下來正則引擎將對結束標籤之前的字元進行惰性符合,直到遇到一個「</」符號。然後正則表達式中的「1」表示對前面符合的組「([A-Z][A-Z0-9]*)」進行引用,在本例中,被引用的是標籤名「B」。所以需要被符合的結尾標籤為「</B>」

你可以對相同的後向引用組進行多次引用,<<([a-c])x1x1>>將符合「axaxa」、「bxbxb」以及「cxcxc」。如果用數字形式引用的組沒有有效的符合,則引用到的內容簡單的為空。

一個後向引用不能用於它自身。<<([abc]1)>>是錯誤的。因此你不能將<< >>用於一個正則表達式符合本身,它只能用於置換操作中。

後向引用不能用於字集內定。<<(a)[1b]>>中的<<1>>並不表示後向引用。在字集內定,<<1>>可以被解釋為八進位形式的轉碼。

向後引用會降低引擎的速度,因為它需要存儲符合的組。如果你不需要向後引用,你可以告訴引擎對某個組不存儲。例如:<<Get(?:Value)>>。其中「(」後面緊跟的「?:」會告訴引擎對於組(Value),不存儲符合的值以供後向引用。

    重複操作與後向引用

當對組使用重複操作符時,快取裡後向引用內容會被不斷重整,只保留最後符合的內容。例如:<<([abc]+)=1>>將符合「cab=cab」,但是<<([abc])+=1>>卻不會。因為([abc])第一次符合「c」時,「1」代表「c」;然後([abc])會繼續符合「a」和「b」。最後「1」代表「b」,所以它會符合「cab=b」。

應用:檢查重複單詞–當編輯文字時,很容易就會輸入重複單詞,例如「the the」。使用<<(w+)s+1>>可以檢驗到這些重複單詞。要刪除第二個單詞,只要簡單的利用置換功能置換掉「1」就可以了。

    組的命名和引用

在PHP,Python中,可以用<<(?P<name>group)>>來對組進行命名。在本例中,詞法?P<name>就是對組(group)進行了命名。其中name是你對組的起的名字。你可以用(?P=name)進行引用。

.NET的命名組

.NET framework也支援命名組。不幸的是,微軟的程式員們決定發明他們自己的語法,而不是沿用Perl、Python的規則。目前為止,還沒有任何其他的正則表達式實現支援微軟發明的語法。

下面是.NET中的例子:

(?<first>group)(?』second』group)

正如你所看到的,.NET提供兩種詞法來建立命名組:一是用尖括號「<>」,或是用單引號「』』」。尖括號在字串中使用更方便,單引號在ASP代碼中更有用,因為ASP代碼中「<>」被用作HTML標籤。

要引用一個命名組,使用k<name>或k』name』.

當進行搜尋置換時,你可以用「${name}」來引用一個命名組。

12.  正則表達式的符合模式

本教學所討論的正則表達式引擎都支援三種符合模式:

<</i>>使正則表達式對大小寫不敏感,

<</s>>開啟「單行模式」,即點號「.」符合新行符

<</m>>開啟「多行模式」,即「^」和「$」符合新行符的前面和後面的位置。

    在正則表達式內定開啟或關閉模式

如果你在正則表達式內定插入修飾符(?ism),則該修飾符只對其右邊的正則表達式起作用。(?-i)是關閉大小寫不敏感。你可以很快的進行測試。<<(?i)te(?-i)st>>應該符合TEst,但是不能符合teST或TEST.

13.  原子組與防止回溯

在一些特殊情況下,因為回溯會使得引擎的效率極其低下。

讓我們看一個例子:要符合這樣的字串,字串中的每個欄位間用逗號做分隔設定,第12個欄位由P開頭。

我們容易想到這樣的正則表達式<<^(.*?,){11}P>>。這個正則表達式在標準情況下工作的很好。但是在極端情況下,如果第12個欄位不是由P開頭,則會發生災難性的回溯。如要搜尋的字串為「1,2,3,4,5,6,7,8,9,10,11,12,13」。首先,正則表達式一直完成符合直到第12個字元。這時,前面的正則表達式消耗的字串為「1,2,3,4,5,6,7,8,9,10,11,」,到了下一個字元,<<P>>並不符合「12」。所以引擎進行回溯,這時正則表達式消耗的字串為「1,2,3,4,5,6,7,8,9,10,11」。繼續下一次符合過程,下一個正則符號為點號<<.>>,可以符合下一個逗號「,」。然而<<,>>並不符合字元「12」中的「1」。符合失敗,繼續回溯。大家可以想像,這樣的回溯組合是個非常大的數量。因此可能會造成引擎崩潰。

用於阻止這樣巨大的回溯有幾種專案:

一種簡單的專案是盡可能的使符合精確。用取反字集代替點號。例如我們用如下正則表達式<<^([^,
]*,){11}P>>,這樣可以使失敗回溯的次數下降到11次。

另一種專案是使用原子組。

原子組的目的是使正則引擎失敗的更快一點。因此可以有效的阻止海量回溯。原子組的語法是<<(?>正則表達式)>>。位於(?>)之間的所有正則表達式都會被認為是一個單一的正則符號。一旦符合失敗,引擎將會回溯到原子組前面的正則表達式部分。前面的例子用原子組可以表達成<<^(?>(.*?,){11})P>>。一旦第十二個欄位符合失敗,引擎回溯到原子組前面的<<^>>。

14.  向前檢視與向後檢視

Perl 5 引入了兩個強大的正則語法:「向前檢視」和「向後檢視」。他們也被稱作「零長度斷言」。他們和錨定一樣都是零長度的(所謂零長度即指該正則表達式不消耗被符合的字串)。不同之處在於「前後檢視」會實際符合字元,只是他們會拋棄符合只返回符合結果:符合或不符合。這就是為什麼他們被稱作「斷言」。他們並不實際消耗字串中的字元,而只是斷言一個符合是否可能。

幾乎本文討論的所有正則表達式的實現都支援「向前嚮後檢視」。唯一的一個例外是Javascript只支援向前檢視。

    肯定和否定式的向前檢視

如我們前面提過的一個例子:要尋找一個q,後面沒有緊跟一個u。也就是說,要麼q後面沒有字元,要麼後面的字元不是u。採用否定式向前檢視後的一個解決專案為<<q(?!u)>>。否定式向前檢視的語法是<<(?!檢視的內容)>>。

肯定式向前檢視和否定式向前檢視很類似:<<(?=檢視的內容)>>。

如果在「檢視的內容」部分有組,也會產生一個向後引用。但是向前檢視本身並不會產生向後引用,也不會被計入向後引用的編號中。這是因為向前檢視本身是會被拋棄掉的,只保留符合與否的判斷結果。如果你想保留符合的結果作為向後引用,你可以用<<(?=(regex))>>來產生一個向後引用。

    肯定和否定式的先後檢視

向後檢視和向前檢視有相同的效果,只是方向相反

否定式向後檢視的語法是:<<(?<!檢視內容)>>

肯定式向後檢視的語法是:<<(?<=檢視內容)>>

我們可以看到,和向前檢視相比,多了一個表示方向的左尖括號。

例:<<(?<!a)b>>將會符合一個沒有「a」作前導字元的「b」。

值得注意的是:向前檢視從現用的字串位置開始對「檢視」正則表達式進行符合;向後檢視則從現用的字串位置開始先後回溯一個字元,然後再開始對「檢視」正則表達式進行符合。

    深入正則表達式引擎內定

讓我們看一個簡單例子。

把正則表達式<<q(?!u)>>應用到字串「Iraq」。正則表達式的第一個符號是<<q>>。正如我們知道的,引擎在符合<<q>>以前會掃過整個字串。當第四個字元「q」被符合後,「q」後面是空字元(void)。而下一個正則符號是向前檢視。引擎注意到已經進入了一個向前檢視正則表達式部分。下一個正則符號是<<u>>,和空字元不符合,從而導致向前檢視裡的正則表達式符合失敗。因為是一個否定式的向前檢視,意味著整個向前檢視結果是完成的。於是符合結果「q」被返回了。

我們在把相同的正則表達式應用到「quit」。<<q>>符合了「q」。下一個正則符號是向前檢視部分的<<u>>,它符合了字串中的第二個字元「i」。引擎繼續走到下個字元「i」。然而引擎這時注意到向前檢視部分已經處理完了,並且向前檢視已經完成。於是引擎拋棄被符合的字串部分,這將導致引擎回退到字元「u」。

因為向前檢視是否定式的,意味著檢視部分的完成符合導致了整個向前檢視的失敗,因此引擎不得不進行回溯。最後因為再沒有其他的「q」和<<q>>符合,所以整個符合失敗了。

為了確保你能清楚地理解向前檢視的實現,讓我們把<<q(?=u)i>>應用到「quit」。<<q>>首先符合「q」。然後向前檢視完成符合「u」,符合的部分被拋棄,只返回可以符合的判斷結果。引擎從字元「i」回退到「u」。由於向前檢視完成了,引擎繼續處理下一個正則符號<<i>>。結果發現<<i>>和「u」不符合。因此符合失敗了。由於後面沒有其他的「q」,整個正則表達式的符合失敗了。

    更進一步理解正則表達式引擎內定機制

讓我們把<<(?<=a)b>>應用到「thingamabob」。引擎開始處理向後檢視部分的正則符號和字串中的第一個字元。在這個例子中,向後檢視告訴正則表達式引擎回退一個字元,然後檢視是否有一個「a」被符合。因為在「t」前面沒有字元,所以引擎不能回退。因此向後檢視失敗了。引擎繼續走到下一個字元「h」。再一次,引擎暫時回退一個字元並檢查是否有個「a」被符合。結果發現了一個「t」。向後檢視又失敗了。

向後檢視繼續失敗,直到正則表達式到達了字串中的「m」,於是肯定式的向後檢視被符合了。因為它是零長度的,字串的現用的位置仍然是「m」。下一個正則符號是<<b>>,和「m」符合失敗。下一個字元是字串中的第二個「a」。引擎向後暫時回退一個字元,並且發現<<a>>不符合「m」。

在下一個字元是字串中的第一個「b」。引擎暫時性的向後退一個字元發現向後檢視被滿足了,同時<<b>>符合了「b」。因此整個正則表達式被符合了。作為結果,正則表達式返回字串中的第一個「b」。

    向前嚮後檢視的應用

我們來看這樣一個例子:尋找一個具有6位字元的,含有「cat」的單詞。

首先,我們可以不用向前嚮後檢視來解決問題,例如:

<< catw{3}|wcatw{2}|w{2}catw|w{3}cat>>

足夠簡單吧!但是當需求變成尋找一個具有6-12位字元,含有「cat」,「dog」或「mouse」的單詞時,這種方法就變得有些笨拙了。

我們來看看使用向前檢視的專案。在這個例子中,我們有兩個基本需求要滿足:一是我們需要一個6位的字元,二是單詞含有「cat」。

滿足第一個需求的正則表達式為<<w{6}>>。滿足第二個需求的正則表達式為<<w*catw*>>。

把兩者結合起來,我們可以得到如下的正則表達式:

<<(?=w{6})w*catw*>>

具體的符合過程留給讀者。但是要注意的一點是,向前檢視是不消耗字元的,因此當判斷單詞滿足具有6個字元的條件後,引擎會從開始判斷前的位置繼續對後面的正則表達式進行符合。

最後作些改善,可以得到下面的正則表達式:

<<(?=w{6})w{0,3}catw*>>

15.  正則表達式中的條件測試

條件測試的語法為<<(?ifthen|else)>>。「if」部分可以是向前嚮後檢視表達式。如果用向前檢視,則語法變為:<<(?(?=regex)then|else)>>,其中else部

分是可選的。

如果if部分為true,則正則引擎會試圖符合then部分,否則引擎會試圖符合else部分。

需要記住的是,向前先後檢視並不實際消耗任何字元,因此後面的then與else部分的符合時從if測試前的部分開始進行嘗試。

16.  為正則表達式加入註釋

在正則表達式中加入註釋的語法是:<<(?#comment)>>

例:為用於符合有效日期的正則表達式加入註釋:

(?#year)(19|20)dd[- /.](?#month)(0[1-9]|1[012])[- /.](?#day)(0[1-9]|[12][0-9]|3[01])
原文出處:http://imsiren.com/archives/560

PHP程式設計問題諮詢:
請什麼是UBB代碼?使用UBB代碼有何好處?

PHP程式設計問題回覆:
UBB代碼,可以參考以下的說明:

UBB代碼是HTML的一個變種,是Ultimate Bulletin Board (國外一個BBS程式,國內也有不少地方使用這個程式)採用的一種特殊的TAG.
即使禁止使用 HTML,你也可以用 UBBCode? 來實現.也許你更希望使用 UBBCode? 而不是 HTML, 即使論壇允許使用 HTML, 因為使用起來代碼較少也更安全.

PHP攫取代碼案例,支援正則表達式設定從開始到結束區功能變數,代碼如下:

<?php     
function preg_substr($start, $end, $str) // 正則截取函數     
{     
    $temp = preg_split($start, $str);     
    $content = preg_split($end, $temp[1]);     
    return $content[0];     
}  
function str_substr($start, $end, $str) // 字串截取函數     
{     
    $temp = explode($start, $str, 2);     
    $content = explode($end, $temp[1], 2);     
    return $content[0];     
}  
// —————- 使用案例 —————-  
$str = iconv("UTF-8", "big5", file_get_contents("http://www.mycodes.net"));   
echo ('標題: ' . str_substr("<title>", "</title>", $str)); // 通過字串提取標題  
echo ('作者: ' . preg_substr("/userid=d+">/", "/<//", $str)); // 通過正則提取作者  
echo ('內容: ' . str_substr('<div class="content">', '</div>', $str)); //內容當然不可以少  
?>   

FPDF的功能確實很強大,但它是如何實現PDF檔案生成的呢,我決定深入分析一下它的代碼,以求對其進行改進,應用到自己的項目中。

FPDF實際上是一個類,由於該類在php4和5下都能標準運行,那麼就從PHP4的角度來分析它。
首先從類的屬性、構造函數開始,然後按類的公共方法的順序進行分析,遇到呼叫其他方法的時候將其提前進行分析。

首先來看類的屬性:
var $page;               // 現用的頁數    
var $n;                  // 現用的對像數    
var $offsets;            //array of object offsets    
var $buffer;             // PDF 快取    
var $pages;              // 包括頁數的陣列    
var $state;              // 現用的文件狀態    
var $compress;           // 壓縮標示    
var $k;                  // 比例因子(使用者指定單位內的點)    
var $DefOrientation;     // 預設方向    
var $CurOrientation;     // 現用的方向    
var $PageFormats;        // 可用的頁格式    
var $DefPageFormat;      // 預設的頁格式    
var $CurPageFormat;      // 現用的的頁格式    
var $PageSizes;          // 儲存非預設頁面大小的陣列    
var $wPt,$hPt;           // 用點表示的現用的頁尺寸    
var $w,$h;               // 使用者指定單位表示的現用的頁尺寸    
var $lMargin;            // 頁面左邊距    
var $tMargin;            // 頁面上邊距    
var $rMargin;            // 頁面右邊距    
var $bMargin;            // 換版邊    
var $cMargin;            // 內定單元邊距    
var $x,$y;               // 使用者單位表示的現用的坐標    
var $lasth;              // 最近輸出單元的高度    
var $LineWidth;          // 使用者單位表示的線寬,即粗細    
var $CoreFonts;          // 標準字型名稱的陣列    
var $fonts;              // 用到的字型的陣列    
var $FontFiles;          // 字型檔案的陣列    
var $diffs;              // 編碼差異的陣列    
var $FontFamily;         // 現用的字型    
var $FontStyle;          // 現用的字型樣式    
var $underline;          // 下劃線標示    
var $CurrentFont;        // 現用的字型訊息    
var $FontSizePt;         // 用點表示現用的字型大小    
var $FontSize;           // 使用者單位表示現用的字型大小    
var $DrawColor;          // 繪圖彩色指令    
var $FillColor;          // 填充彩色指令    
var $TextColor;          // 文字彩色指令    
var $ColorFlag;          // 指出填充彩色和文字彩色是否不同    
var $ws;                 // 文字間距    
var $images;             // 用到的圖片的陣列    
var $PageLinks;          // 頁面連結的陣列    
var $links;              // 內定連結的陣列    
var $AutoPageBreak;      // 自動分頁    
var $PageBreakTrigger;   // 自動分頁的觸發值,即最大內容高度    
var $InHeader;           // 處理頁眉時的標示    
var $InFooter;           // 處理頁腳時的標示    
var $ZoomMode;           // 顯示時的縮放模式    
var $LayoutMode;         // 分頁顯示模式    
var $title;              // 檔案標題    
var $subject;            // 檔案主旨    
var $author;             // 檔案作者    
var $keywords;           // 檔案關鍵詞    
var $creator;            // 應用程式,不知道啥意思,PDF屬性裡的    
var $AliasNbPages;       // 頁面總數的別名,用於在該位置顯示頁面總數    
var $PDFVersion;         // PDF 版本號  

這裡把註釋換成了中文的,僅供參考吧!

在網站PHP程式網頁中,如何生成靜態頁面的方法?

在PHP網站開發中為了網站推廣和SEO等需要,需要對網站進行全站或局部靜態化處理,PHP生成靜態HTML頁面有多種方法,比如利用PHP範本、快取等實現頁面靜態化,今天就以PHP案例教學形式討論PHP生成靜態頁面的方法。頁面靜態化的方法,分為兩種,一種是偽靜態,就是url 重寫,一種是你真的靜態化。下面介紹PHP中頁面靜態化的方法。

什麼是PHP靜態化

PHP靜態化的簡單理解就是使網站生成頁面以靜態HTML的形式展現在訪客面前,PHP靜態化分純靜態化和偽靜態化,兩者的區別在於PHP生成靜態頁面的處理機制不同。

PHP生成靜態HTML頁面的方法

1、利用PHP範本生成靜態頁面

PHP範本實現靜態化非常方便,比如安裝和使用PHP Smarty實現網站靜態化。

2、使用PHP檔案讀寫功能生成靜態頁面

PHP生成靜態頁面案例代碼

    <?
    $out1 = "<html><head><title>PHP網站靜態化教學</title></head>
    <body>歡迎訪問PHP網站開發教學網http://por.tw,本文主要介紹PHP網站頁面靜態化的方法
    </body></html>";
    $fp = fopen("leapsoulcn.html","w");
    if(!$fp)
    {
    echo "System Error";
    exit();
    }
    else {
    fwrite($fp,$out1);
    fclose($fp);
    echo "Success";
    }
    ?>

    3、使用PHP輸出控制函數(Output Control)生成靜態頁面

    輸出控制函數(Output Control)也就是使用和控制快取來生成靜態HTML頁面,也會使用到PHP檔案讀寫函數。

    PHP生成靜態頁面案例代碼
        <?
        ob_start();
        echo "<html>".
        "<head>".
        "<title>PHP網站靜態化教學</title>".
        "</head>".
        "<body>歡迎訪問PHP網站開發教學網http://por.tw,本文主要介紹PHP網站頁面靜態化的方法</body>".
        "</html>";
        $out1 = ob_get_contents();
        ob_end_clean();
        $fp = fopen("leapsoulcn.html","w");
        if(!$fp)
        {
        echo "System Error";
        exit();
        }
        else
        {
        fwrite($fp,$out1);
        fclose($fp);
        echo "Success";
        }
        ?>

        我們知道使用PHP進行網站開發,一般執行結果直接輸出到遊覽器,為了使用PHP生成靜態頁面,就需要使用輸出控制函數控制快取區,以便取得快取區的內容,然後再輸出到靜態HTML頁面檔案中以實現網站靜態化。

        PHP生成靜態頁面的思路為:首先開啟快取,然後輸出了HTML內容(你也可以通過include將HTML內容以檔案形式包括進來),之後取得快取中的內容,清理快取後通過PHP檔案讀寫函數將快取內容寫入到靜態HTML頁面檔案中。PHP檔案讀寫教學?

        獲得輸出的快取內容以生成靜態HTML頁面的過程需要使用三個函數:ob_start()、ob_get_contents()、ob_end_clean()。

        網站PHP程式網頁生成靜態頁面的方法知識點:

        1、ob_start函數一般主要是用來開啟快取,注意使用ob_start之前不能有任何輸出,如空格、字元等。

        2、ob_get_contents函數主要用來取得快取中的內容以字串形式返回,注意此函數必須在ob_end_clean函數之前呼叫,否則取得不到快取內容。

        3、ob_end_clean函數主要是清理快取中的內容並關閉快取,完成則返回True,失敗則返回False

        PHP輸出控制函數(Output Control)有很多應用,今後將陸續展開。

        至此,使用PHP生成靜態HTML頁面以實現網站靜態化的方法就介紹完了,根據實際情況和需求你可以選取不同的靜態化方法。

用php生成UTF-8的檔案沒有什麼特別的,只要把我們執行的那個PHP檔案改成UTF-8編碼儲存起來,然後頁面內容也用UTF-8的編碼就可以了。

代碼如下:

header('Content-Type: text/html; charset=utf-8');
$text=」荊門線上 0724.CC 普通文字帶漢字生成」;
$f=fopen("0724.php", 「wb」);
fwrite($f, $text);
fclose($f);
?>

這樣雖然上面定義了utf-8生成的是 utf-8 的格式,我們來簡單的改下就可以了  因為這樣儲存的檔案在記事中檢視並不是utf-8的編碼,所以我們看下面代碼

$xml = '網路線上 普通文字帶中文字生成';
$h = fopen (0725.php,'w');
if ($h) {
  fwrite ($h,"xEFxBBxBF".iconv('utf-8','utf-8',$xml));
}
fclose ($h);

前面這個 xEFxBBxBF 一定不能忘記呀

OK,這時候生成的檔案就是我們要的 utf-8格式的編碼檔案。

網站發生警語:atal error: Allowed memory size of 16777216 bytes exhausted(記憶體不夠用)之處理方法

網站架站或網站升級後,網站發生類似警語:atal error: Allowed memory size of XXXXXXXX bytes exhausted
不管是管理介面(Dashboard),或者登入出問題,看來幾乎都是記憶體不夠用。

例如其發生的警語:
Fatal error: Allowed memory size of 16777216 bytes exhausted (tried to allocate 4023 bytes)

這是什麼意思呢?又該如何解決?
答案是:記憶體的需求是更大了,這邊提供幾個解決的方法。

當出現以下的類似情況,要來調整PHP的記憶體,來執行更多的程式
1.找到php.ini的路徑(/etc/php5/apache2/php.ini)
2.搜尋:memory_limit 字串
3.找到:memory_limit = 16M      ; Maximum amount of memory a script may consume (16MB)

A.如果有權限修改php.ini,那麼請將memory_limit = 32M的32提高,看是要64還是96或者128。
    
B.如果沒有權限修改php.ini,可以在.htaccess裡面加上php_value memory_limit 32M,或者更高的數字。

備註:php.ini修改後apache要重新啟動才會生效!

語法如下:
service apache2 restart

————————————————————-

如何使用PHP執行linux系統指令呢?
相信這是很多學員想知道答案!

首先先要給大家介紹PHP執行linux系統指令的幾個基本函數。

system函數

說明:執行外部程式並顯示輸出資料。
語法:string system(string command, int [return_var]);
返回值: 字串

詳細介紹:
本函數就像是 C 語中的函數 system(),用來執行指令,並輸出結果。若是 return_var 參數存在,則執行 command 之後的狀態會填入 return_var 中。同樣值得注意的是若需要處理使用者輸入的資料,而又要防止使用者耍花招破解系統,則可以使用 EscapeShellCmd()。若 PHP 以模組式的執行,本函數會在每一行輸出後自動更新 Web 伺服器的輸出緩衝暫存區。若需要完整的返回字串,且不想經由不必要的其它中間的輸出介面,可以使用 PassThru()。

案例代碼:
< ?php
$last_line = system('ls', $retval);
echo 'Last line of the output: ' . $last_line;
echo '<hr />Return value: ' . $retval;
?>

exec函數
說明:執行外部程式。
語法:string exec(string command, string [array], int [return_var]);
返回值: 字串

詳細介紹:
本函數執行輸入 command 的外部程式或外部指令。
它的返回字串只是外部程式執行後返回的最後一行;若需要完整的返回字串,可以使用 PassThru() 這個函數。

要是參數 array 存在,command 會將 array 加到參數中執行,若不欲 array 被處理,可以在執行 exec() 之前呼叫 unset()。
若是 return_var 跟 array 二個參數都存在,則執行 command 之後的狀態會填入 return_var 中。

值得注意的是若需要處理使用者輸入的資料,而又要防止使用者耍花招破解系統,則可以使用 EscapeShellCmd()。

案例代碼:
<?php
echo exec('whoami');
?>  

popen函數
說明:開啟檔案。
語法:int popen(string command, string mode);
返回值: 整數

詳細介紹:
本函數執行指令開檔,而該檔案是用管道模式處理的檔案。
用本函數開啟的檔案只能是單向的 (只能讀或只能寫),而且一定要用 pclose() 關閉。
在檔案操作上可使用 fgets()、fgetss() 與 fputs()。若是開檔發生錯誤,返回 false 值。

案例代碼:
<?
$fp = popen( "/bin/ls", "r" );
?>  

資料加密在我們生活中的地位已經越來越重要了,尤其是考慮到在網路上發生的大量交易和傳輸的大量資料。
對於不需要復原為原始資料的訊息我們可以使用MD5、sha1等不可逆加密算法對資料進行加密處理,但對於交易訊息等需要復原為原始資料的重要訊息則必須使用可復原的加密算法進行加密了。
當然你可以自己寫一個可逆加密的算法進行加密和解密計算。
本文中我們介紹的是使用 mcrypt模組進行加密解密操作。

Mcrypt的優點不僅僅在於其提供的加密算法較多,在windows下隨PHP包一起發佈,還在於它可以對資料進行加/解密處理,此外,它還提供了內含DES算法在內的35種處理資料用的函數。
/**
 +—————————————————–
 * Mcrypt 加密/解密
 * @param String $date 要加密和解密的資料
 * @param String $mode encode 預設為加密/decode 為解密
 * @return String
 +—————————————————–
 * @example
 */
function ZxingCrypt($date,$mode = 'encode'){
    $key = md5('zxing');//用MD5哈希生成一個密鑰,注意加密和解密的密鑰必須統一
    if ($mode == 'decode'){
        $date = base64_decode($date);
    }
    if (function_exists('mcrypt_create_iv')){
        $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
    }
    if (isset($iv) && $mode == 'encode'){
        $passcrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $date, MCRYPT_MODE_ECB, $iv);
    }elseif (isset($iv) && $mode == 'decode'){
        $passcrypt = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $date, MCRYPT_MODE_ECB, $iv);
    }
    if ($mode == 'encode'){
        $passcrypt = base64_encode($passcrypt);
    }
    return $passcrypt;
}

—————————————————————-