2010-11-22 17 views
2

Kullanacağımız bir sistemde "uses" adlı bir işlev var. Pascal'ı biliyorsanız, kullanım cümlesi, programınıza bağımlılıklarının neler olduğunu (C ve PHP'ye benzer şekilde) söyler. Bu işlev, içerme (_once) veya gerektiren (_once) dışındaki dosya eklerini kontrol etmek için kullanılıyor.PHP Sabit dize parametreleri belirteci

Test prosedürlerinin bir parçası olarak, statik olarak yüklenmiş dosyalar için bir bağımlılık görselleştirme aracı yazmam gerekiyor.

Statik Yüklü Örnek: uses('core/core.php','core/security.php');

Dinamik Yüklü Örnek: uses('exts/database.'.$driver.'.php'); kod değil çalışırken, statik olarak test edilir çünkü dinamik yük durumları filtrelemek için gereken

.

$inuses=false; // whether currently in uses function or not 
$uses=array(); // holds dependencies (line=>file) 
$tknbuf=array(); // last token 
foreach(token_get_all(file_get_contents($file)) as $token){ 
    // detect uses function 
    if(!$inuses && is_array($token) && $token[0]==T_STRING && $token[1]=='uses')$inuses=true; 
    // detect uses argument (dependency file) 
    if($inuses && is_array($token) && $token[0]==T_CONSTANT_ENCAPSED_STRING)$tknbuf=$token; 
    // detect the end of uses function 
    if($inuses && is_string($token) && $token==')'){ 
     $inuses=false; 
     isset($uses[$tknbuf[2]]) 
      ? $uses[$tknbuf[2]][]=$tknbuf[1] 
      : $uses[$tknbuf[2]]=array($tknbuf[1]); 
    } 
    // a new argument (dependency) is found 
    if($inuses && is_string($token) && $token==',') 
     isset($uses[$tknbuf[2]]) 
      ? $uses[$tknbuf[2]][]=$tknbuf[1] 
      : $uses[$tknbuf[2]]=array($tknbuf[1]); 
} 

Not:

Bu

ben şu anda kullanıyorum kodudur Ben argümanları algılamak için bir devlet motorunu kullanıyorum olduğunu bilmek yardımcı olabilir.

Sorunum? Fonksiyona girebilecek her türlü argüman olduğu için, onu doğru bulmak çok zor. Belki de doğru yaklaşımı kullanmıyorum, ancak, ben bu durumda en iyi token_get_all kullanarak eminim. Bu yüzden sorun aslında o kadar iyi olmayan devlet motorum. Kolay yolu kaçırıyor olabilirim, bazı hakem değerlendirmelerini alacağımı düşündüm.

Düzenleme: Bu sefer ne yaptığımı açıklamaya yaklaşımı aldım, ancak tam olarak ne istediğimi değil. Basit kelimelerle, "uses" adlı bir işleve iletilen argüman dizisini almam gerekiyor. Mesele, argümanlar hakkında biraz spesifik olduğum; Sadece bir dizi düz diziye ihtiyacım var, hiç dinamik kod yok (sabitler, değişkenler, işlev çağrıları ...).

+1

Neden sadece derslerin otomatik yüklenmesini kullanmadığını sorun. – Mchl

+0

Gerçekten, regex = evil meme hakkında unutun. Bu **, onlar için bir kullanım durumudur. – mario

+0

@Mchl - Çünkü bu özellikle sınıfları ilgilendirmiyor. @Mario - Kuşkusuz, regex ile çok iyi değilim. Her iki durumda da, PHP kodlarını ayrıştırmak için regex oluşturmak ve çalıştırmak oldukça yavaştır. – Christian

cevap

1

Tamam Çalışıyorum. Sadece devlet motoruna bazı küçük düzeltmeler. Kısaca, argüman tokenleri doğrudan kullanım dizisine konmak yerine tamponlanır. Ardından, her ',' veya ')' belirtecin geçerli olup olmadığını kontrol edip kullanım dizisine ekledim.

$inuses=false; // whether currently in uses function or not 
$uses=array(); // holds dependencies (line=>file) 
$tknbuf=array(); // last token 
$tknbad=false; // whether last token is good or not 
foreach(token_get_all(file_get_contents($file)) as $token){ 
    // detect uses function 
    if(!$inuses && is_array($token) && $token[0]==T_STRING && $token[1]=='uses')$inuses=true; 
    // token found, put it in buffer 
    if($inuses && is_array($token) && $token[0]==T_CONSTANT_ENCAPSED_STRING)$tknbuf=$token; 
    // end-of-function found check buffer and throw into $uses 
    if($inuses && is_string($token) && $token==')'){ 
     $inuses=false; 
     if(count($tknbuf)==3 && !$tknbad)isset($GLOBALS['uses'][$file][$tknbuf[2]]) 
       ? $GLOBALS['uses'][$file][$tknbuf[2]][]=$tknbuf[1] 
       : $GLOBALS['uses'][$file][$tknbuf[2]]=array($tknbuf[1]); 
     $tknbuf=array(); $tknbad=false; 
    } 
    // end-of-argument check token and add to $uses 
    if($inuses && is_string($token) && $token==','){ 
     if(count($tknbuf)==3 && !$tknbad)isset($GLOBALS['uses'][$file][$tknbuf[2]]) 
      ? $GLOBALS['uses'][$file][$tknbuf[2]][]=$tknbuf[1] 
      : $GLOBALS['uses'][$file][$tknbuf[2]]=array($tknbuf[1]); 
     $tknbuf=array(); $tknbad=false; 
    } 
    // if current token is not an a simple string, flag all tokens as bad 
    if($inuses && is_array($token) && $token[0]!=T_CONSTANT_ENCAPSED_STRING)$tknbad=true; 
} 

Düzenleme: Aslında hala hatalı (farklı bir sorun olsa da). Ama yeni düşünmem gereken güzel bir fikir.

+0

Bir 'kullanımlar' işlevine girdikten sonra, yinelemeliyim: a) okuma belirteci, b) eğer belirteci == '(', bire bir ekleyin. C) eğer sayaç> 0 ise: ')' aldırmamak. d) Eğer karşı == 0: eğer ')' yapılır. eğer ',' baştan başla; başka listeye belirteci ekleyin. Geçerli liste (d adımından sonra) tek bir sabit dizgeden başka bir şey değilse, onu bağımlılıklara ekleyebilirsiniz. Yine, aptal değil, ama muhtemelen yeterince iyi. – Matthew

1

kullanma düzenli ifadeler:

uses('bar.php', 'test.php', $foo->bar()); 
uses(bar('test.php'), 'file.php'); 
uses(bar(foo('a','b','c')), zed()); 

Verimlerine:

<?php 
preg_match_all('/uses\s*\((.+)\s*\)/', 
    file_get_contents('uses.php'), $matches, PREG_SET_ORDER); 

foreach ($matches as $set) { 
    list($full, $match) = $set; 

    echo "$full\n"; 

    // try to remove function arguments 
    $new = $match; 
    do { 
    $match = $new; 
    $new = preg_replace('/\([^()]*\)/', '', $match); 
    } while ($new != $match); 

    // iterate over each of the uses() args 
    foreach (explode(',', $match) as $arg) { 
    $arg = trim($arg); 
    if (($arg[0] == "'" || $arg[0] == '"') && substr($arg,-1) == $arg[0]) 
    echo " ".substr($arg,1,-1)."\n"; 
    } 
} 
?> 

karşı Running

uses('bar.php', 'test.php', $foo->bar()) 
    bar.php 
    test.php 
uses(bar('test.php'), 'file.php') 
    file.php 
uses(bar(foo('a','b','c')), zed()) 

kod denir nasıl biliyorsanız Açıkçası sınırlamaları ve varsayımları vardır, ama yeterli olabilir.