2013-03-10 69 views
0

我在一些PHP代碼中摸不着頭腦。我不知道它是否在邏輯上還能正常工作,因爲我對PHP很陌生,並且由於語法錯誤而無法執行:syntax error, unexpected 'use' (T_USE), expecting '{'PHP:從全局函數訪問封閉範圍

語法錯誤在use上跳動,儘管PHP版本完全支持它,並且語法(據我所知)是正確的。

該代碼檢查指定哪個數據庫實現,並且它將定義它的功能。因爲我無法將從其他函數返回的函數定義爲全局函數,所以我將它存儲在變量中,通過全局函數「包裝」訪問,從外部範圍捕獲變量,或者至少應該這樣做。

這兩條線產生的錯誤已被標記: -

function query_escaper($element_escaper) { 
    return function($query, $values) use ($element_escaper) { 
     return join(array_map(
      function($query_elem, $value) { 
       return isset($value) 
        ? $query_elem . $element_escaper($value) 
        : $query_elem 
        ; 
      }, 
      explode('?', $query), 
      $values 
     )); 
    }; 
} 

function define_postgresql_functions() { 

    [...] 

    $escape_query = query_escaper('pg_escape_literal'); 

    # 
    # XXX The error occurs here :- 
    # 
    function escape_query() use ($escape_query) { 
     return call_user_func_array($escape_query, func_get_args()); 
    } 

    [...] 
} 

function define_mysql_functions() { 

    [...] 

    $escape_query = query_escaper(function($str) { 
     return use_database(function($database) use ($str) { 
      return $database->real_escape_string($str); 
     }); 
    }); 

    # 
    # XXX The same error also occurs here :- 
    # 
    function escape_query() use ($escape_query) { 
     return call_user_func_array($escape_query, func_get_args()); 
    } 

    [...] 
} 

switch ($database_info['type']) { 
case 'postgresql': 
    define_postgresql_functions(); 
    break; 
case 'mysql': 
    define_mysql_functions(); 
    break; 
default: 
    throw new DatabaseNotImplementedException(); 
} 

我找了兩個可能的解決方案:要麼能夠捕獲來自外部範圍的變量,或者定義全局功能的另一種方式從其他函數返回的函數。

+0

您運行的是什麼版本的PHP? – mkaatman 2013-03-10 03:11:22

+0

mkaatman,我正在運行5.4的香草副本。 馬里奧,我已經瘋狂與trialling括號,以免混淆解析器。 – ljackman 2013-03-10 03:12:55

回答

1

模式function\s+\w+總是在全局範圍內聲明一個函數,這意味着您必須使用全局語法。這意味着如果你創建一個閉包,你不能命名這個函數。因此,這是無效的:

function escape_query() use ($escape_query) { 

但是這會很好地工作:

$escape_function = function() use ($escape_query) { 

有幾種不同的方式來完成你想要的。想起eval,就像在函數中使用靜態變量或OOP解決方案一樣。

我認爲OOP解決方案可能是最簡單的:

class Escaper { 

    public static $escape_function; 
} 


// in your function 
Escaper::$escape_function = function() use ($escape_query) { //... 

// later 
Escaper::$escape_function('a','b','c'); 
+0

啊,爲了捕捉封閉的範圍,我需要關閉。我如何將閉包定義爲全局函數?我用eval編寫了一個令人討厭的黑客攻擊,但我寧願做其他事情...... – ljackman 2013-03-10 03:17:17

+0

感謝您的說明性編輯。 – ljackman 2013-03-10 03:21:57