日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

php预处理_如何用预处理让 PHP 更先进

發布時間:2024/7/5 php 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 php预处理_如何用预处理让 PHP 更先进 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原標題:如何用預處理讓 PHP 更先進

先來點趣事。不久以前, 來添加 Python 的 range 語法。然后, 大蝦 ,并且 建議為 PHP 添加 C# 風格的 getter 和 setter。

我意識到對于一個局外人來說,建議和實現新的語言特性是件緩慢的事情,所以我打開了自己的編輯器……

這篇教程的代碼可以在 上找到。它在 PHP^7.1 版本測試,生成的代碼可以運行在 PHP^5.6|^7.0。

宏是如何運行的?

從我上次談及宏,已經有一段時間了(也許你從來沒有聽說過他們)。為了更新存儲空間,他們會采用類似這樣的代碼:

macro { →(···expression)} >> { ··stringify(···expression)}macro { T_VARIABLE·A[ ···range ]} >> { eval( '$list = '. →(T_VARIABLE·A) . ';'. '$lower = '. explode( '..', →(···range))[ 0] . ';'. '$upper = '. explode( '..', →(···range))[ 1] . ';'. 'return array_slice($list, $lower, $upper - $lower);')}

…并將自定義的 PHP 語法,如下所示:

$few = many[ 1.. 3];

…轉化為合法的 PHP 語法,如下所示:

$few= eval( '$list = '. '$many'. ';'. '$lower = '. explode( '..', '1..3')[0] . ';'. '$upper = '. explode( '..', '1..3')[1] . ';'. 'return array_slice($list, $lower, $upper - $lower);');

如果你想了解這是如何運行的,可以查看我之前發布的 。

秘訣是理解解析器的如何分割代碼字符串,構建一個宏模式,然后將該模式遞歸地應用于新的語法之上的。

但是 沒有很好的文檔。我們很難知道模式究竟是什么樣子的,或者最終生成什么樣的有效語法。每個新的應用程序都要求編寫一個類似這樣的教程,其他人才能真正理解發生了什么。

創建基準代碼

所以,讓我們來看看手邊的應用程序。我們模仿 C# 的語法向 PHP 添加 getter 和 setter 語法。在我們可以做到這一點之前,我們需要有一個好的基準代碼,用于后續開發。 也許是某種形式的trait,我們可以將其添加到需要這個新功能的類中。

我們需要實現代碼來檢查類定義,并為每個特殊屬性或注釋動態創建 getter 和 setter 方法。

也許我們可以從定義一個特殊方法名稱的格式開始,并且使用 __get 和 __set 方法:

namespaceApp; traitAccessorTrait{ /** * @inheritdoc* * @paramstring $property * @parammixed $value */publicfunction__get($property){ if(method_exists( $this, "__get_{$property}")) { return$this->{ "__get_{$property}"}(); } } /** * @inheritdoc* * @paramstring $property * @parammixed $value */publicfunction__set($property, $value){ if(method_exists( $this, "__set_{$property}")) { return$this->{ "__set_{$property}"}($value); } }}

每個以 __get_ 和 __set_ 命名開始的方法都需要與一個尚未定義的屬性相關聯。我們可以參考類似下面的語法:

namespace App; classSprocket{ private$ type{ get { return$ this-> type; } set { $ this-> type= strtoupper($value); } };}

…被轉化為和下面非常類似的格式:

namespaceApp; classSprocket{ useAccessorTrait; private$type; privatefunction__get_type(){ return$this->type; } privatefunction__set_type($value){ $this->type = strtoupper($value); }}

定義所需的宏是這些工作中最難的部分。鑒于文檔缺乏(和未廣泛使用),并且只有少數有用的異常消息,這里面大多是反復驗證和試錯的結果。

我花了幾個小時整理出以下幾種模式:

macro ·unsafe { ·ns()· class{ ···body }} >> {· class{ useAccessorTrait; ···body }}macro ·unsafe { privateT_VARIABLE· var{ get { ···getter } set { ···setter } };} >> { privateT_VARIABLE· var; privatefunction··concat(__get_ ··unvar(T_VARIABLE·var))(){ ···getter } privatefunction··concat(__set_ ··unvar(T_VARIABLE·var))($value){ ···setter }}

好吧,讓我們看看這兩個宏是做什么的:

我們從匹配 class MyClass {...} 開始,并插入我們之前構建的 AccessorTrait。 這里提供了 _get 和 _set 的實現,其中將 _get_bar 鏈接到 print $class->bar 中。

我們匹配 accessor 塊的語法,并將其替換為通用的屬性定義,后面是幾個獨立的方法定義。 我們可以在這些函數中封裝 get{...} 和 set{...} 塊的實現部分。

起初,當你運行這個代碼時,你會遇到一個錯誤。這是因為 ··unvar 函數不是宏處理器的標準組件。這是我不得不添加的部分,從 $type 到 type 的轉換:

namespaceYayDSLExpanders; useYayToken; useYayTokenStream; functionunvar(TokenStream $ts): TokenStream{ $str = str_replace( '$', '', (string) $ts); returnTokenStream::fromSequence( newToken( T_CONSTANT_ENCAPSED_STRING, $str ) ) ;}

我本可以拷貝(幾乎全部)的 stringify 擴展器的代碼,它是包含在宏解析器代碼之中。為了弄清楚 Yay 如何實現的,你不需要了解很多關于 Yay 內部結構。將 TokenStream 轉換為 string(在此上下文中)意味著你正在獲取當前token所標記的字符串的值 - 在本例中為 ··unvar(T_VARIABLE·var) - 并對其執行字符串操作。

(string) $ts 變成“$type”,而不是“T_VARIABLE·var”。

通常,當這些宏被放置在要處理的腳本中,會自動完成這些。換句話說,我們可以創建一個類似于下面的腳本:

<?phpmacro ·unsafe { ...} >> { ...}macro ·unsafe { ...} >> { ...}namespace App; traitAccessorTrait{ ...} classSprocket{ private$ type{ get { return$ this-> type; } set { $ this-> type= strtoupper($value); } };}

…然后我們可以用下面命令運行它:

vendor/bin/yay src/Sprocket.pre >>src/Sprocket.php

最后,我們就可以使用這些代碼了(需要 Composer PSR-4 autoloading):

require__DIR__. "/vendor/autoload.php";$sprocket = newAppSprocket();$sprocket->type = "acme sprocket"; print$sprocket->type; // Acme Sprocket自動轉換

手動過程就是這樣子。在每次更改 src/Sprocket.pre 時誰會想去運行這個 bash 命令呢? 幸運的是,我們可以將其自動化!

第一步是定義自定義的自動加載器:

spl_autoload_register( function($class){ $definitions = require__DIR__. "/vendor/composer/autoload_psr4.php"; foreach($definitions as$prefix => $paths) { $prefixLength = strlen($prefix); if(strncmp($prefix, $class, $prefixLength) !== 0) { continue; } $relativeClass = substr($class, $prefixLength); foreach($paths as$path) { $php = $path . "/". str_replace( "", "/", $relativeClass) . ".php"; $pre = $path . "/". str_replace( "", "/", $relativeClass) . ".pre"; $relative = ltrim(str_replace( __DIR__, "", $pre), DIRECTORY_SEPARATOR); $macros = __DIR__. "/macros.pre"; if(file_exists($pre)) { // ... convert and load file} } }}, false, true);

如 中所述,你可以將此文件保存為 autoload.php,并使用 files 自動加載功能,通過 Composer 的自動加載器包含它。

該定義的第一部分直接來自于 的示例實現。我們獲得 Composer 的 PSR-4 定義文件,對于每個前綴,我們檢查它是否與當前正在加載的類匹配。

如果匹配,我們檢查每個可能的路徑,直到我們找到一個 file.pre,其中定義了我們的自定義語法。 之后,我們獲得 macros.pre 文件的內容(在項目基目錄中),并創建一個臨時文件 - 使用 macros.pre 內容+匹配的文件的內容命名。這意味著宏在傳遞給 Yay 的文件中可用。 待 Yay 編譯完 file.pre.interim→file.php 之后,我們就刪除 file.pre.interim。

這個處理過程的代碼如下:

if(file_exists($php)) { unlink($php);}file_put_contents( "{$pre}.interim", str_replace( "<?php ", file_get_contents($macros), file_get_contents($pre) )); exec( "vendor/bin/yay {$pre}.interim >> {$php}");$comment = " # This file is generated, changes you make will be lost. # Make your changes in {$relative} instead.";file_put_contents( $php, str_replace( "<?php ", "<?phpn{$comment}", file_get_contents($php) )); unlink( "{$pre}.interim");require_once $php;

注意,在調用 spl_autoload_register 結束時的那兩個布爾值。第一個是標示這個自動加載器是否應該拋出異常加載錯誤。 第二個是標示這個自動加載器是否應該預先加載到堆棧中。 這把它放在 Composer 自動加載器之前,這意味著我們可以在 Composer 嘗試加載 file.php 之前轉換 file.pre!

創建一個插件框架

這種自動化實現很棒,但如果在每個項目中都重新操作是非常浪費的。 如果我們可以僅添加一個 composer require 依賴(為獲得一個新的語言功能)就可以正常工作,這怎么樣呢?讓我們試試看......

首先,我們需要創建一個新的 repo,包含以下文件:

composer.json→ 自動加載下列文件

functions.php→ 創建宏路徑函數(在其他庫中可以動態添加自己的宏文件)

expanders.php→ 創建擴展器函數,比如 ··unvar

autoload.php→ augment Composer 的自動加載器,將每個其他庫的宏文件加載到每個編譯的 .prefile 中{

"name":

"pre/plugin",

"require": {

"php":

"^7.0",

"yay/yay":

"dev-master"},

"autoload": {

"files": [

"functions.php",

"expanders.php",

"autoload.php"] },

"minimum-stability":

"dev",

"prefer-stable":

true}

上面代碼來自 composer.json

上面代碼來自 functions.php

你可能正在想著使用 $GLOBALS 作為存儲宏文件路徑。這并不重要,因為我們可以使用諸多其他方式來存儲這些路徑。 這里僅僅是演示模式實現的最簡單的方法。

這部分來自 expanders.php

<?phpnamespacePre ;if(file_exists(__DIR__. "/../../autoload.php")) { define("BASE_DIR", realpath(__DIR__. "/../../../"));}spl_autoload_register(function($class){ $definitions = requireBASE_DIR . "/vendor/composer/autoload_psr4.php"; foreach($definitions as$prefix => $paths) { // ...check $prefixLengthforeach($paths as$path) { // ...create $php and $pre$relative = ltrim(str_replace(BASE_DIR, "", $pre), DIRECTORY_SEPARATOR); $macros = BASE_DIR . "/macros.pre"; if(file_exists($pre)) { // ...remove existing PHP fileforeach(getMacroPaths() as$macroPath) { file_put_contents( "{$pre}.interim", str_replace( "<?php ", file_get_contents($macroPath), file_get_contents($pre) ) ); } // ...write and include the PHP file} } }}, false, true);

這部分來自 autoload.php

現在,附加的宏插件可以使用這些函數將自己的代碼掛接到系統中了...

創建新的語言功能

通過構建插件代碼,我們可以將我們的類訪問器重構為獨立的、可自動應用的功能。 我們需要創建幾個文件來實現這一點:

composer.json→ 用于查找基本插件庫并自動加載以下文件

macros.pre→ 當前插件的宏代碼

functions.php→ 將 accessor 宏掛接到基本插件系統中

src/AccessorsTrait.php→ 大致上保持不變{

"name":

"pre/class-accessors",

"require": {

"php":

"^7.0",

"pre/plugin":

"dev-master"},

"autoload": {

"files": [

"functions.php"],

"psr-4": {

"Pre":

"src"} },

"minimum-stability":

"dev",

"prefer-stable":

true}

這是來自 composer.json

namespacePre;addMacroPath( __DIR__. "/macros.pre");

這是來自 functions.php

macro · unsafe{ ·ns()· class{ ···body }} >> { · class{ use PreAccessorsTrait; ···body }}macro · unsafe{ privateT_VARIABLE·variable { get{ ···getter } set{ ···setter } };} >> { // ...}macro · unsafe{ privateT_VARIABLE·variable { set{ ···setter } get{ ···getter } };} >> { // ...}macro · unsafe{ privateT_VARIABLE·variable { set{ ···setter } };} >> { // ...}macro · unsafe{ privateT_VARIABLE·variable { get{ ···getter } };} >> { // ...}

這是來自 macros.pre

這個宏文件比以前的版本更冗長。可能有一個更優雅的方式來處理所有的關于 accessors 重定義的排列,但我目前還沒有找到。

整合在一起

現在,一切都很好地打包了,你可以直接使用語言功能。 看看這個快速演示!

你可以在 Github 上找到這些插件庫:

結語

和所有的東西一樣,這可能被濫用。 宏也不例外。雖然它在概念上很酷, 但這個代碼絕對不是產品級代碼。

本文來自:https://www.oschina.net/translate/how-to-make-modern-php-more-modern-with-preprocessing

關注微信公眾號:PHP技術大全

PHPer升級為大神并不難!返回搜狐,查看更多

責任編輯:

總結

以上是生活随笔為你收集整理的php预处理_如何用预处理让 PHP 更先进的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 99在线小视频 | 亚洲一区 视频 | 美女亚洲一区 | 精品国产av无码一区二区三区 | 翔田千里在线播放 | 青青草婷婷 | 国产三级短视频 | 免费看国产精品 | 春物催眠 | 三区在线 | 91精品国产闺蜜国产在线闺蜜 | 亚洲精品一区二区三区中文字幕 | 色婷婷av一区二区三区四区 | 国产精品网址 | 成人影视免费 | 四虎av影院| www.亚洲成人 | va在线播放 | 国产中年熟女高潮大集合 | 亚洲一区在线观看视频 | 熟妇人妻va精品中文字幕 | 久久免费视频网站 | 视频在线a | 黄色aa毛片| 一级黄色大片 | 久久另类ts人妖一区二区 | 好吊妞视频这里只有精品 | 日本wwwwww| 一级片av| 国产在线观看www | 男人看片网站 | 男人的天堂在线播放 | 欧美爱爱网站 | 日韩欧美国产一区二区三区在线观看 | 国产视频亚洲 | 日本成人精品视频 | 中文字幕日韩电影 | 中文字幕无线精品亚洲乱码一区 | 黄色在线网 | 午夜激情久久 | 五月激情六月 | 国产视频一区二区三区在线观看 | 成人免费网站在线 | 人妻91麻豆一区二区三区 | 美女隐私免费观看 | 色婷婷av一区二区三 | 亚洲涩网 | 欧美黄色成人 | 人妻无码一区二区三区久久 | 亚洲精品欧美激情 | 就要操就要日 | 日韩午夜免费 | 麻豆一区二区三区四区 | 中文字幕日韩精品无码内射 | 97色干 | 一级国产黄色片 | 日本免费黄色网 | 邪恶久久 | 国产又大又粗又爽的毛片 | 欧美aaaaaaa| 国产高清视频网站 | 亚洲a图| 免费的毛片视频 | 亚洲精品国产熟女久久久 | 国产又色又爽又黄又免费 | 色综合图片区 | 51ⅴ精品国产91久久久久久 | 色婷婷精品国产一区二区三区 | 国产精品久久久久久免费观看 | 日韩高清一二三区 | 波多野结衣潜藏淫欲 | 精品久久久久久久久中文字幕 | 国产aⅴ一区二区三区 | 一区二区视频在线免费观看 | 人人九九精 | 婷婷av一区二区三区 | 姑娘第5集高清在线观看 | 一极黄色大片 | 精品一区二区三区无码视频 | 色噜噜狠狠成人中文 | 亚洲欧美日韩免费 | 国产一二三视频 | 日本人妖xxxx | 久热超碰| 最近的中文字幕在线看视频 | www成人在线 | 日本三区视频 | 少妇精品一区二区 | 成人欧美一区二区三区 | 欧美成人女星 | 超碰97免费 | av中文字幕免费观看 | 国产清纯白嫩初高中在线观看性色 | 亚洲一区二区三区四区不卡 | 激情宗合 | 亚洲狼人色 | 后入内射欧美99二区视频 | 欧美成人专区 | 国产精品乱码一区 |