[Modern PHP] 第三章 標準

來源:互聯網
上載者:User
PHP組件和架構的數量多的讓人難以置信。有像Symfony和Laravel這樣的巨型架構,也有像Silex和Slim這樣的微型架構。甚至還有些在現代PHP組件出現之前就存在很久的傳統架構,例如CodeIgniter。現代PHP生態系統是一個名副其實的代碼大熔爐,這有助於開發人員們構造令人驚奇的應用。


不幸的是,那些老的PHP架構都是在相對封閉的環境下開發出來的,它們沒法與其他的PHP架構共用代碼。如果你的項目使用某個老的PHP架構,你會牢牢被困在架構之中,陷入架構自身的生態系統而不能自拔。如果你對架構本身提供的工具還算滿意,那麼這種相對集中的環境倒也沒有什麼問題。但是,如果使用了CodeIgniter架構的同時還想從Symfony架構中挑選幾個優秀的類庫來使用,那你可能就沒有那麼幸運了,除非你自己專門為你的項目寫個一次性的適配器。


what we've got here is a failure to communicate(在這裡我們完全無法溝通)

--電影鐵窗喋血的經典台詞


看到問題所在了嗎?封閉的環境中開發出來的架構它們的設計初衷就不是為了和其它架構進行互連。無論是對開發人員來說(被所選擇的架構限制了創造力)還是對架構自身(他們重複開發著某些已經存在的代碼)來說,這種設計方式是非常低效的。儘管如此,我還是有好訊息要告訴大家。PHP社區對架構的認識已經從集中式架構模型過渡到了由高效、公用、專一的組件構成的分布式生態系統。


PHP-FIG的營救計劃


一些PHP架構的開發人員們意識到這個問題,於是他們在2009年的php|tek(著名的PHP會議)上進行了討論。討論的核心是如何提升架構內部的互連性和開發效率。譬如,如果某個PHP架構可以分享出一個monolog這樣的非耦合的日誌類,那麼我們是不是就不用每次都去開發一個新的緊耦合的日誌記錄類了?如果某個PHP架構可以使用Symfony架構的symfon/httpfoundation組件中的優秀的HTTP request和response類,那麼我們是不是就不需要開發自己的HTTP request和response類了?為了實現這個目標,PHP架構需要使用某種通用的語言來實現互動以及分享它們的架構。而它們需要的就是標準。


這些在php|tek會議上偶遇的PHP架構的開發人員們最終建立了PHP Framwork Interop Group(PHP-FIG)。PHP-FIG就是由一群PHP架構項目的代表組成的,按照PHP-FIG的官方網站的說法,他們的職責就是“討論各自項目的共性從而找到可以協同工作的方式”。PHP-FIG制定了一些推薦(recommendations),PHP的架構可以自願選擇是否實現這些recommendations以提高互動性並共用各自的架構。


PHP-FIG是一群PHP架構項目的代表自創的組織。它的會員並不是通過選舉產生的,除了滿懷著發展PHP社區的意願外這些會員並沒有什麼特別之處。任何人都可以申請會員資格。任何人都可以對處於提議階段的PHP-FIG recommendations提交自己的反饋。最終的PHP-FIG recommendations通常被採納並被許多最大最流行的PHP架構實現。我非常鼓勵你參與到PHP-FIG之中,你只要做到發送你的反饋、協助你最喜愛的PHP架構一起打造未來。


我們常說PHP-FIG負責提供各種recommendations,理解這一點非常重要,因為推薦不等同於規則,推薦不是必須要執行的。這些recommendations都是經過審慎考慮、精雕細琢的建議,它們可以為PHP開發人員們(甚至PHP架構的作者們)帶來更多的便利。


架構協作


PHP-FIG的任務是實現架構協作。而架構協作意味著通過介面、自動載入和編碼風格來實現協同工作。


介面


PHP架構之間通過共用的介面協同工作。架構通過PHP介面可以確認第三方依賴庫提供的了哪些方法,而無需考慮這些依賴庫是如何?這些介面的。


參考第二章,可以瞭解PHP介面的詳細說明。


舉個例子,某個PHP架構很開心的分享了一個第三方的logger對象,假設這個對象實現了emergency()、alert()、critical()、error()、warning()、notice()、info()和debug()這幾個方法。這些方法具體是怎麼實現的無關緊要。每個架構只需要關心第三方依賴庫是否實現了這些方法就行。


介面使得PHP開發人員們可以構造、分享和使用功能專一的組件取代龐大的架構。


自動載入


PHP架構之間通過自動載入協同工作。通過自動載入功能,PHP解譯器在運行時可以自動定位並根據需要來載入一個PHP類。


在PHP標準制定之前,PHP組件和架構使用魔術函數\_autoload()或者更進階點的spl_autoload_register()方法來實現它們自己獨立的自動載入器。這迫使我們需要去熟悉每個組件和架構各自特有的自動載入器才能使用它們。現如今,絕大多數現代PHP組件和架構都與公用的自動載入器標準相容。這意味著我們可以使用一個統一的自動載入器將多個PHP組件組合并匹配在一起使用。


編碼風格


PHP架構之間通過編碼風格來協同工作。你的編碼風格決定了空格、大小寫以及括弧的位置(尤其重要)。如果所有的PHP架構都能統一一套標準的編碼風格,那麼PHP開發人員們就不需要每次在使用新的PHP架構時還得去適應新的編碼風格,PHP架構的代碼就不會顯得那麼陌生。一套標準的編碼風格還能降低項目中新人的入門門檻,這樣他們就可以集中精力去解決bug,而不用花大量的事件去學習陌生的編碼風格。


標準的編碼風格還能改進我們自己的項目。每個開發人員都有在編碼上的獨特癖好,當開發人員們在同一個程式碼程式庫上一起工作時麻煩就會出現。一套標準的編碼風格能夠協助所有的團隊成員立刻明白同一個程式碼程式庫中彼此的代碼而不用去管代碼的作者是誰。


PSR是什嗎?


PSR是PHP standards recommendation(PHP推薦標準)的縮寫。如果你最近閱讀過一些PHP方面的部落格,你或許已經看到了一些諸如PSR-1、PSR-2、PSR-3這樣的術語。這些都是PHP-FIG的推薦。他們的名字以PSR-開頭,結尾跟著一個數字編號。每個PHP-FIG的推薦都是用來解決在大多數PHP架構中經常遇到的特定問題的。為了不讓各種PHP架構不斷的去解決同樣的問題,它們可以採納這些PHP-FIG的推薦,在共用的解決方案基礎上構建各自架構。


截止到本書發行為止,PHP-FIG已經發布了5個推薦:

  • PSR-1:基本編碼風格
  • PSR-2:嚴格編碼風格
  • PSR-3:Logger介面
  • PSR-4:自動載入

  • 如果你數一數會發現只有4個推薦,沒錯,PHP-FIG已經廢棄了最早的PSR-0推薦。最初的推薦已經被最新的PSR-4所取代。



    注意PHP-FIG的這些推薦正好完美匹配了我之前提到的協同工作的三種方式:介面、自動載入和編碼風格。這不是巧合。



    對於PHP-FIG的這些推薦我真的感到很興奮。它們是現代PHP生態系統下的基石。它們定義了PHP組件和架構協同工作的方法。我承認,討論PHP標準並不是一個吸引眼球的話題,但是它們(在我心中)是瞭解現代PHP的前提。



    PSR-1:基本編碼風格



    如果你想讓自己寫的代碼能夠相容PHP社區標準,從PSR-1起步。這是使用起來最簡單的標準。它非常簡單,以至於你都沒有意識到或許自己已經在使用這些標準了。PSR-1提供了不需要花太大精力就可以實施的簡單指導原則。PSR-1的設計目的就是提供一個可以參與到PHP架構中的基準編碼風格。要與PSR-1標準相容你需要滿足下面的幾個需求:


    PHP標籤

    你必須將你的PHP程式碼封裝含在或者標籤之間。你不可以使用其它任何PHP標籤文法。


    字元編碼

    所有的PHP檔案必須使用不包含byte order mark(位元組順序標記)(BOM)的UTF-8編碼。這聽起來有點麻煩,但是大多數編輯器或者IDE都可以替你自動處理


    檔案用途

    在一個單獨的PHP檔案中,要麼在裡面定義聲明(一個類、trait、函數或者常量等),要麼執行一個能產生結果的操作(譬如輸出資訊或者修改資料)。但是不可以兩者兼顧。對於你來說這是一個簡單的任務,只需要一點點的前瞻性和計劃性。


    自動載入

    你的PHP名字空間和類必須支援PSR-4自動載入標準。你要做的就是為你的PHP聲明起一個合適的名字並保證它們的定義檔案儲存在正確的路徑。我們稍後會討論PSR-4。


    類名

    你的PHP類名必須使用公用的CamelCase(大寫駝峰)格式。這個格式也稱作TitleCase。例如CoffeeGrinder、CoffeeBean和PourOver。


    常量名

    你的PHP常量必須全部大寫。如果需要的話可以使用底線來分隔單詞。例如WOOT、LET_OUR_POWERS_COMBINE和GREAT_SCOTT。


    方法名

    你的PHP方法名必須使用公用的camelCase(小寫駝峰)格式。這意味著方法名的首字母都是小寫,而隨後的每個子單詞的首字母仍然是大寫。例如 phpIsAwesome、iLoveBacon和tennantIsMyFavoriteDoctor。


    PSR-2:嚴格編碼風格


    在實現了PSR-1標準後,下一步就是實現PSR-2標準。PSR-2標準定義了包含更嚴格的指導原則的PHP編碼風格。



    PSR-2編碼風格是全世界的眾多貢獻者賜予PHP架構的禮物,他們分享了各自特有的編碼風格和偏好。公用的嚴格的編碼風格使得開發人員們能夠寫出對其他人來說簡單易懂的代碼。



    與PSR-1不同,PSR-2推薦包含了更嚴格的指導原則。有些PSR-2的指導原則可能並不如你所願。然而PSR-2還是大多數流行PHP架構首選的編碼風格。沒必要一定得使用PSR-2,但是如果使用了的話,對別的開發人員來說你的PHP代碼的可讀性和可用性會獲得到大大的提升。


    建議你使用更嚴格的PSR-2編碼風格,即使我用了嚴格這個詞,但是寫起來還是很簡單的,事實上多寫寫就習慣了。另外,還有一些可以自動將代碼自動格式化為PSR-2風格的工具可供我們使用。


    實現PSR-1

    PSR-2編碼風格的前提是你必須先實現PSR-1編碼風格


    縮排

    這是兩大陣營之間的熱門話題。一方更偏愛使用一個tab定位字元來進行代碼縮排。而另一方(更酷的一方)更偏愛使用幾個空格來實現代碼縮排。PSR-2推薦規定PHP代碼應該使用四個空格進行縮排


    根據個人經驗,空白字元更適合縮排,因為空白格在不同的代碼編輯器中的寬度幾乎都是一樣的。而一個tab定位字元的寬度在不同的代碼編輯器中卻各不相同。使用四個空白字元來縮排代碼可以保證你的代碼的最佳的視覺一致性。


    檔案和行

    你的PHP檔案必須使用Unix換行(LF)作為每行的結束,檔案末尾必須有一個空行,不可以使用 ?> PHP標籤作為結束。每行代碼不應該超過80個字元。即使放寬標準,但是說到底每行的代碼也不可以超過120個字元。每行的末尾都不可以有多餘的空格。這些聽起來工作量不少,但是這都是必不可少的。大多數的代碼編輯器都可以自動的將代碼按照寬度換行、過濾末尾的Null 字元以及使用Unix換行結尾。所有的這些問題都應該自動處理,而不需要你每次來考慮。


    最初我認為忽略結尾的 ?> PHP標籤是個很奇怪的要求。但是忽略結束標籤來避免未知的輸出錯誤確實是一個很好的習慣。如果你在檔案末尾使用了?>結束標籤,之後又在後面多了一個空行,這個空行會被當作輸出從而導致錯誤(譬如當你使用header函數設定HTTP頭時)。


    關鍵詞

    我知道許多PHP開發人員們會以全大寫的形式來書寫TRUE、FALSE和NULL。如果你是這麼做的,請嘗試忘掉這種習慣從現在開始轉而使用全小寫寫法。PSR-2推薦指出所有的PHP關鍵詞都需要以全小寫形式書寫。


    名字空間

    每個名字空間的聲明之後必須有一個空行。同樣的,當你使用use關鍵詞來匯入名字空間或者其別名時,你也必須在use聲明之後加上一個空行,請看下面的例子:


    namespace My\Component;use Symfony\Components\HttpFoundation\Request;use Symfony\Components\HttpFoundation\Response;class App{    // 類的定義體}

    和縮排一樣,類定義中的括弧位置也是引發另一個強烈爭議的話題。有些人喜歡將開始括弧放在類名後的同一行中,而另一些人更喜歡另起一行,將開始括弧放在類名後新的一行中。PSR-2推薦指出,類定義的開始括弧必須像下面的例子中一樣放在類名的定義語句後的新的一行中。類定義的結束括弧必須放置在類定義體末尾之後新的一行中。或許你早就按照我們說的做了,所以沒什麼大不了的。如果你的類繼承自其它的類或者實現了其它的介面,extends和implements關鍵詞必須與類名保持在統一行中:


       

    方法

    方法定義中的括弧位置與類定義的括弧位置一樣。方法定義的開始括弧放到方法名之後新的一行中。方法定義的結束括弧放到方法定義體末尾的新的一行中。注意方法的參數。第一個圓括弧之後不可以有空格,而最的圓括弧之前也不可以有空格。每個方法的參數(除了最後一個)後都緊跟著一個逗號和一個空格:


       
    範圍

    你必須給每個類的屬性和方法聲明一個範圍。範圍是public、protected或者private之一,範圍決定了一個屬性或者方法在類的內部或者外部是否可以被訪問。老派的PHP開發人員們可能習慣了在類的屬性前加上var關鍵詞以及在私人方法前加上底線_。千萬別學他們這麼做,你必須使用前面介紹的三個範圍之一。如果你需要將一個類的屬性或者方法聲明為abstract或者final,那麼abstract和final修飾符必須放到範圍之前。如果你將一個屬性或者方法聲明為靜態,static修飾符必須放在範圍之後:


       
    控制結構

    這可能是我最容易犯錯的指導原則。所有的控制結構的關鍵詞都必須跟隨一個單獨的Null 字元。控制結構關鍵詞包括了:if、elseif、else、switch、case、while、do while、for、foreach、try、catch。如果控制結構關鍵詞需要使用一對圓括弧,請確保第一個圓括弧後面不要加空格,以及最後一個圓括弧前面不要加空格。與類和方法的定義不同,開始括弧必須放在控制結構關鍵詞之後,並保持與控制結構關鍵詞在同一行中。控制結構關鍵詞的結束括弧必須另起一行。下面用一個簡單的例子來說明這些指導原則:


    isAwake() === true) {    do {        $gorilla->beatChest();    } while ($ibis->isAsleep() === true);    $ibis->flyAway();}

    你可以自動相容PSR-1和PSR-2編碼風格。許多代碼編輯器依照PSR-1和PSR-2來自動格式化你的代碼。另外,還有些工具可以協助你依照PHP標準來檢查並且格式化你的代碼。譬如 PHP Code Sniffer,我們常稱之為phpcs,通過這個工具(可以直接在命令列中使用或者在IDE裡使用)可以報告出你的代碼與給定的PHP代碼標準之間的差異。你可以通過幾乎所有的包管理系統(譬如PEAR、Homebrew、Aptitude或者Yum)來安裝phpcs。

    你還可以使用Fabien Potencier的 PHP-CS-Fixer來自動修正絕大多數的代碼不相容性。這個工具雖然還不夠完美,但是有了它你只需要花很少的精力就可以保證儘可能的遵循PSR相容性。


    PSR-3:Logger介面



    第三個PHP-FIG的推薦標準並不像前面那些一樣,它不是一組指導原則。PSR-3是一個介面,它指定了可以用來實現PHP logger組件的方法。



    一個logger是一個可以依照各種不同的重要程度來將資訊寫到給定輸出的對象。記錄下的資訊可以用來分析、檢查和修正應用程式的操作、穩定性和效能。例如在開發過程中將調試資訊寫入到文字檔中,將網站訪問統計儲存到資料庫中,或者將致命錯誤的分析報告通過郵件發送網站管理員。目前最流行的PHP logger組件是 monolog/monolog,作者是Jordi Boggiano。



    許多PHP架構在日誌記錄上有著不同的需求。在PHP-FIG成立之前,每個架構解決日誌記錄的方式都各不相同,通常都會有一套自己特有的實現。本著協同工作和專業化(現代PHP不變的主題)的精神,PHP-FIG建立了PSR-3 logger介面。架構接受相容PSR-3的logger來實現兩個重要的目標:將日誌記錄的開發工作交給第三方來完成,架構的使用者可以選擇他們喜歡的logger組件。對大家來說這是一個雙贏的結果。



    寫一個PSR-3的Logger類


    一個相容PSR-3推薦標準的PHP logger組件必須包含一個實現了Psr\Log\LoggerInterface介面的類。PSR-3介面複製了 RFC 5424 系統日誌協議並且定義了九個方法:


       
    每個介面方法都對應了RFC 5424協議的一個層級並接收兩個參數。第一個參數$message必須是一個字串或者是一個包含了__toString()方法的對象。第二個參數$context是可選的,它提供了一個數組用來儲存預留位置對應的值,以便替換第一個參數中的標記(預留位置)。



    使用$context參數可以構造出複雜的logger資訊。你可以在資訊中使用placeholders(預留位置)。一個預留位置看起來就像{placeholder_name}這樣,它有開始花括弧、預留位置名稱、結束花括弧組成。預留位置中不可以包含空格。而$context參數是一個關聯陣列,它的鍵就對應著預留位置的名稱(兩個括弧中間部分),而它的值可以用來替換訊息文本中對應的預留位置。



    要寫一個PSR-3的logger,建立一個新的PHP類,實現Psr\Log\Logger介面並為每個介面方法提供具體的實現就可以了。


    使用PSR-3 Logger


    如果你在開發自己的PSR-3 logger,趕緊收手,好好考慮一下你這樣浪費時間是否明智。我強烈不建議你去開發自己的logger,為什嗎?因為現在已經有了一些堪稱完美的PHP logger組件可供使用。


    如果你需要一個PSR-3的logger,直接使用monolog/monolog就好了。別浪費事件到處尋找了。Monolog組件全面實現了PSR-3介面,而且它非常便於使用自訂訊息格式化工具和handlers進行擴充。Monolog的訊息handlers允許你將日誌訊息發送到文字檔、syslog、郵箱、HipChat、Slack、網路伺服器、遠程API、資料庫以及任何你可以想象的地方。在某種極端的情況下,如果Monolog無法提供一個handler來滿足你奇葩的輸出目標,開發一個你自己的Monolog訊息handler並整合到Monolog中也是非常簡單的。例子 3-1 示範了設定Monolog並將訊息記錄到文字檔中是多麼的簡單:


    例子 3-1 使用Monolog


    pushHandler(new StreamHandler('logs/development.log', Logger::DEBUG));$log->pushHandler(new StreamHandler('logs/production.log', Logger::WARNING));// 使用 logger$log->debug('This is a debug message');$log->warning('This is a warning message');

    PSR-4:autoloader


    第四個PHP-FIG的推薦標準描述了一個標準化的autoloader策略。autoloader是一個用來在運行時按需求尋找PHP類、介面或者trait並將它們載入到PHP解譯器中的策略。支援PSR-4 autoloader標準的PHP組件和架構可以通過一個唯一的autoloader定位並載入到PHP解譯器中。很多可協同工作的組件能夠關聯到現代PHP生態系統中,PSR-4功不可沒。


    為什麼autoloader這麼重要


    你是不是經常在你的PHP檔案頂部看到這樣的代碼?


       
    經常看到,對嗎?你可能對require()、require_once()、include()和inluce_once()函數已經非常熟悉了。這些函數用來將一個外部的PHP檔案載入到當前指令碼中,如果你的PHP指令碼不多的話,這樣的代碼工作起來完全沒有問題。但是,如果你需要包含上百個PHP指令碼呢?如果你需要包含上千個指令碼呢?這就暴露出了require()和include()函數的擴充問題,這也是PHP autoloader之所以這麼重要的原因。一個 autoloader是一個用來 在運行時按需求尋找PHP類、介面或者trait並將它們載入到PHP解譯器中的策略,它不需要像前面的例子中那樣明確的指出需要被載入的檔案路徑。



    在PHP-FIG引入PSR-4推薦標準之前,PHP組件和架構的作者們使用__autoload()和spl_autoload_register()函數來註冊自訂的autoloader策略。不幸的是,每個PHP組件和架構的autoloader都是特有的,每個autoloader使用了不同的邏輯來定位和載入PHP類、介面和trait。開發人員們被迫不得不在自己的PHP應用程式初始化時去調用每個組件的autoloader之後才能使用這些組件和架構。我總是喜歡使用Sensio Labs的 Twig模板組件。這個組件真的很棒。然而,如果沒有PSR-4的話,我就不得不去閱讀Twig的文檔才能弄明白如何才能將它自訂的autoloader註冊到我自己應用程式的初始設定檔案中,就像下面這樣:


       
    試想一下,你的應用程式裡的每個PHP組件,你都要去研究一下文檔才能知道如何去註冊它們特有的autoloader。PHP-FIG意識到了這個問題並且提出了PSR-4 autoloader推薦來促進組件的協同工作。多虧有了PSR-4,我們可以只使用一個autoloader來自動載入我們應用程式中的所有PHP組件。太不可思議了。絕大多數現代PHP組件和架構都相容PSR-4。如果你開發並發布了你自己的組件,請確保它們也是相容PSR-4的!讓你的組件也可以和像Symfony、Doctrine、Monolog、Twig、Guzzle、SwiftMailer、PHPUnit、Carbon以及許多其它的組件一樣協同工作。


    PSR-4 Autoloader策略


    如果其它PHP的autoloader一樣,PSR-4描述了一個在運行時定位和載入PHP類、介面以及trait的策略。PSR-4推薦標準並不要求你取修改自己的代碼的實現。事實上,PSR-4隻是給出了如何將你的代碼按檔案系統目錄和PHP名字空間進行組織的建議。PSR-4 autoloader策略依賴於PHP名字空間和檔案系統目錄來定位和載入PHP類、介面和trait。



    PSR-4的實質是將一個頂級的名字空間首碼映射到一個特定的檔案系統目錄上。例如,我可以告訴PHP,所有在\Oreilly\ModernPHP名字空間下的類、介面或者trait都存放在src/這個物理檔案系統目錄下。那麼PHP現在就能知道,任何使用了\Oreilly\ModernPHP這個名字空間首碼的類、介面或者trait都能對應到src/目錄下的子目錄和檔案。例如,\Oreilly\ModernPHP\Chapter1這個名字空間對應到src/Chapter1目錄,而\Oreilly\ModernPHP\Chapter1\Example類對應到src/Chapter1/Example.php檔案。



    PSR-4允許你將一個名字空間首碼映射到一個檔案系統目錄上。名字空間的首碼可以是一個頂級的名字空間。名字空間首碼也可以是一個頂級的名字空間加上任意多個子名字空間。相當的靈活。



    還記得我們在第二章中提到的vendor名字空間嗎?PSR-4 autoloader策略與發布代碼給其他開發人員的組件和架構作者息息相關。一個PHP組件的代碼都在一個唯一的vendor名字空間之下,組件的作者可以指定哪個檔案系統目錄可以與組件的vendor名字空間相對應,就像我前面示範的那樣。我們將在第四章中探索這個概念。



    如何開發一個PSR-4 Autoloader(以及為什麼不建議你這麼做)


    我們知道PSR-4的相容代碼都要有一個與基本檔案系統路徑對應的名字空間。我們也知道名字空間首碼下的子名字空間對應著基本檔案系統目錄的子目錄。例子3-2展示了一個從PHP-FIG網站借來的autoloader的實現,它可以用來尋找並載入基於PSR-4 autoloader策略的類、介面和trait。


    例子 3-2 PSR-4 autoloader


       
    把這段代碼複製粘貼到你的應用程式中,修改$prefix和$base_dir變數,那麼你就擁有了一個自己的可以工作的PSR-4 autoloader。然而,如果你想自己去寫自己的PSR-4 autoloader,趕緊收手並問問自己這樣做是否真的值得。為什嗎?因為我們可以使用Composer依賴管理工具來自動產生PSR-4 autoloader。真的很方便,這就是我將在下面的第四章介紹的。
  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.