php拓展-包管理工具詳解

來源:互聯網
上載者:User

背景

不得不說的是,昨天其實已經是基本上寫完了整個工具了的(Linux上那塊的shell指令碼沒往上添加罷了)。最後整理的時候,犯了個超級大的愚蠢的錯誤。

那就是忘了反選了,呵呵。一下子把原始碼給刪了。WTF!!!後來也使用了一些資料恢複軟體,也沒能成功找回。

於是今天不得不又重寫了一遍,而且僅僅完成了Windows平台上的適配。Linux上的拓展管理,就先不寫了,有時間再進行完善。

原理

在Windows上安裝php的拓展是非常的簡單,而且容易的一件事。

下載拓展對應的dll動態連結程式庫, 然後修改php.ini檔案,最後重啟Apache伺服器。

是的,就是這麼的簡單啦。

下面先說一下這個工具的作用:

  • 爬取目標拓展的連結,做完過濾處理後羅列可以下載得到的拓展庫串連。

  • 解壓下載的zip壓縮包,返回動態連結程式庫存在的位置。

  • 尋找本機php環境變數,找到拓展檔案夾的位置,拷貝動態連結程式庫並修改php.ini檔案內容。

  • 重啟Apache伺服器。即可生效(這個沒有添加自動處理,因為我覺得手動方式會更加理智一點)。

全程我們需要做的就是指定一下要安裝的拓展的名稱,手動的進行選擇要安裝的版本,就是這麼的簡單啦。接下來就一步步地進行分析吧。

下載

這個工具依託的是php官網提供的拓展目錄,

當然也可以使用手動下載安裝的方式,這個工具就是把這個流程自動化了而已。

擷取網頁內容

擷取網頁內容的時候,為了防止網站做了防爬蟲處理,我們採用類比瀏覽器的方式進行。

def urlOpener(self, targeturl):        headers = {                    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36'        }                return urllib2.urlopen(urllib2.Request(url=targeturl, headers=headers)).read()

正則與過濾下載連結

下載了一張網頁,內容還是很多的。而我們需要的僅僅是網頁中預期的下載連結罷了。所以要進行正則匹配,來過濾出我們想要的資料。

而正則有一定的靈活性,所以我們要根據具體情況進行集體的分析,於是我封裝了一個函數。

# 擷取指定拓展的所有能用的版本    def getLinks(self, url, regpattern):        content = self.urlOpener(targeturl=url)        reg = re.compile(regpattern)                return re.findall(reg, content)
def getDownloadLinks(self):        versionLinks = self.getLinks("http://windows.php.net/downloads/pecl/releases/{}".format(self.extensionname),                                             '<A HREF="(/downloads/pecl/releases/{}/.*?)">'.format(self.extensionname))                                   for index, item in enumerate(versionLinks):                                       print "{} : {}".format(index, item)        choice = int(raw_input('Please choose the special version you want by number!\n'))                return versionLinks[choice]    def getTargetUrl(self):        userChoice = "http://windows.php.net"+str(self.getDownloadLinks())                print userChoice        regpattern = '<A HREF="(/.*?/php_.*?\.zip)">.*?<\/A>'        targetUrls = self.getLinks(url=userChoice, regpattern=regpattern)                # 由於正則匹配度寫的不好,第一個連結不能正常匹配,因此採用折斷方式,去除第一個無效連結        return targetUrls[1:]

代碼中很多東西寫得不是通用的,因為這個工具本身就是要依賴於這個網站而是用的。所以沒有做具體的重構處理, 而這已然是足夠的了。

下載預期目標

從上面即可擷取到經由使用者選擇的下載連結,然後我們就可以據此來進行特定版本的拓展包下載了。

def folderMaker(self):        if not os.path.exists(r'./packages/{}'.format(self.extensionname)):            os.mkdir(r'./packages/{}'.format(self.extensionname))                def download(self):        choices = self.getTargetUrl()                for index, item in enumerate(choices):                    print "{} : {}".format(index, item)        choice = int(raw_input('Please choose the special version which suitable for your operation system you want by number!\n'))        userChoice = choices[choice]                # 對外提供友好的使用者提示資訊,最佳化的時候可通過添加進度條形式展現        print 'Downloading, please wait...'        # 開啟下載模式,進行代碼最佳化的時候可以使用多線程來進行加速        data = self.urlOpener(targeturl="http://windows.php.net"+str(userChoice))                # 將下載的資源存放到 本地資產庫(先進行檔案夾存在與否判斷)        filename = userChoice.split('/')[-1]        self.folderMaker()                with open(r'./packages/{}/{}'.format(self.extensionname, filename), 'wb') as file:           file.write(data)                   print '{} downloaded!'.format(filename)

解壓

第一個步驟就是下載,下載的結果就是一個zip壓縮包,所以我們還需要對這個壓縮包進行處理,才能為我們所用。

檔案路徑問題

由於是針對Windows而製作,所以檔案路徑分隔字元就按照windows上的來吧(為了代碼更加優雅,還可以使用os.sep來相容不同的作業系統)。

解壓

def folderMaker(self, foldername):        if not os.path.exists(r'./packages/{}/{}'.format(self.extensionname, foldername)):            os.mkdir(r'./packages/{}/{}'.format(self.extensionname, foldername))                        print 'Created folder {} succeed!'.format(foldername)                def unzip(self):        filelists = [item for item in os.listdir(r'./packages/{}/'.format(self.extensionname)) if item.endswith('.zip')]        filezip = zipfile.ZipFile(r'./packages/{}/{}'.format(self.extensionname, filelists[0]))        foldername = filelists[0].split('.')[0]        self.folderMaker(foldername=foldername)                print 'Uncompressing files, please wait...'        for file in filezip.namelist():            filezip.extract(file, r'./packages/{}/{}/{}'.format(self.extensionname, foldername, file))        filezip.close()                print 'Uncompress files succeed!'

安裝與配置

安裝與配置其實是兩個話題了。

安裝

首先是要將下載好的拓展的dll檔案放置到php安裝目錄下的拓展檔案夾,這個過程就涉及到了尋找php拓展目錄的問題。然後是檔案拷貝的問題。

def getPhpExtPath(self):        # 預設系統中僅有一個php版本        rawpath = [item for item in os.getenv('path').split(';') if item.__contains__('php')][0]        self.phppath = rawpath                return rawpath+str('ext\\')            def getExtensionDllPath(self):            for root, dirs, files in os.walk(r'./packages/{}/'.format(self.extensionname)):                extensionfolder = root.split('\\')[-1]                                if extensionfolder.__contains__('dll'):                                    return root.split('\\')[0] + '/' + extensionfolder+'/'+extensionfolder

代碼未完,下面會把拷貝的那段放上去的。

配置

配置就是需要在php.ini檔案中進行聲明,也就是添加下面的這樣一條語句。(在Dynamic Extension塊下面即可)

extension=XX.dll

 # 針對php.ini檔案中的相關的拓展選項進行針對性的添加.採用的具體方式是使用臨時檔案替換的方法    def iniAppend(self):        inipath = self.phppath+str('php.ini')        tmpinipath = self.phppath+str('php-tmp.ini')                # 要進行替換的新的檔案內容        newcontent = '; Windows Extensions\nextension={}.dll'.format(self.extensionname)        open(tmpinipath, 'w').write(            re.sub(r'; Windows Extensions', newcontent, open(inipath).read()))                    # 進行更名操作        os.rename(inipath, self.phppath+str('php.bak.ini'))                os.rename(tmpinipath, self.phppath+str('php.ini'))                print 'Rename Succeed!'    def configure(self):        # 列印php拓展目錄路徑        extpath = self.getPhpExtPath()+str('php_{}.dll'.format(self.extensionname))                print extpath                # 擷取到拓展動態連結程式庫及其路徑        extensiondllpath = self.getExtensionDllPath()                # 將拓展檔案添加到php拓展目錄中        shutil.copyfile(extensiondllpath, extpath)                # 在php.ini檔案中添加對應的拓展選項        self.iniAppend()                print '{} 拓展已添加,拓展服務將在重啟Apache伺服器後生效!'.format(self.extensionname)

最後讓Apache重啟就可以生效啦。

示範

初始狀態

安裝與配置完畢狀態

啟用狀態

總結

最後來總結一下,這個工具主要使用到了Python語言,方便,優雅,快捷。
完成了對PHP拓展的安裝與配置,大大簡化了操作量。

其實,我覺得使用代碼來完成安裝與配置工作不是很恰當。然而在Windows上也就罷了,畢竟批命令處理起來也不是很好用(PowerShell我沒怎麼用過,所以我沒有發言權。),而要是在Linux上就不一樣了,做一些這樣的任務,使用Shell來寫是最合適不過的了, 而且還可以寫的很靈活。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.