web-dev-qa-db-fra.com

Meilleure façon de supprimer automatiquement les commentaires du code PHP

Quelle est la meilleure façon de supprimer les commentaires d'un fichier PHP?

Je veux faire quelque chose de similaire à strip-whitespace () - mais cela ne devrait pas aussi supprimer les sauts de ligne.

PAR EXEMPLE:

Je veux ceci:

<?PHP
// something
if ($whatsit) {
    do_something(); # we do something here
    echo '<html>Some embedded HTML</html>';
}
/* another long 
comment
*/
some_more_code();
?>

devenir:

<?PHP
if ($whatsit) {
    do_something();
    echo '<html>Some embedded HTML</html>';
}
some_more_code();
?>

(Bien que si les lignes vides restent là où les commentaires sont supprimés, ce ne serait pas correct).

Cela peut ne pas être possible, en raison de l'exigence de préserver le HTML intégré - c'est ce qui a déclenché les choses qui ont été trouvées sur Google.

46
benlumley

J'utiliserais tokenizer . Voici ma solution. Il devrait fonctionner sur les deux PHP 4 et 5:

$fileStr = file_get_contents('path/to/file');
$newStr  = '';

$commentTokens = array(T_COMMENT);

if (defined('T_DOC_COMMENT'))
    $commentTokens[] = T_DOC_COMMENT; // PHP 5
if (defined('T_ML_COMMENT'))
    $commentTokens[] = T_ML_COMMENT;  // PHP 4

$tokens = token_get_all($fileStr);

foreach ($tokens as $token) {    
    if (is_array($token)) {
        if (in_array($token[0], $commentTokens))
            continue;

        $token = $token[1];
    }

    $newStr .= $token;
}

echo $newStr;
52
Ionuț G. Stan

Que diriez-vous d'utiliser php -w pour générer un fichier dépourvu de commentaires et d'espaces, puis d'utiliser un embellisseur comme PHP_Beautifier pour reformater la lisibilité?

42
Paul Dixon
$fileStr = file_get_contents('file.php');
foreach (token_get_all($fileStr) as $token ) {
    if ($token[0] != T_COMMENT) {
        continue;
    }
    $fileStr = str_replace($token[1], '', $fileStr);
}

echo $fileStr;

edit J'ai réalisé que Ionut G. Stan l'a déjà suggéré, mais je vais laisser l'exemple ici

8
Tom Haigh

Voici la fonction publiée ci-dessus, modifiée pour supprimer récursivement tous les commentaires de tous les fichiers php d'un répertoire et de tous ses sous-répertoires:

function rmcomments($id) {
    if (file_exists($id)) {
        if (is_dir($id)) {
            $handle = opendir($id);
            while($file = readdir($handle)) {
                if (($file != ".") && ($file != "..")) {
                    rmcomments($id."/".$file); }}
            closedir($handle); }
        else if ((is_file($id)) && (end(explode('.', $id)) == "php")) {
            if (!is_writable($id)) { chmod($id,0777); }
            if (is_writable($id)) {
                $fileStr = file_get_contents($id);
                $newStr  = '';
                $commentTokens = array(T_COMMENT);
                if (defined('T_DOC_COMMENT')) { $commentTokens[] = T_DOC_COMMENT; }
                if (defined('T_ML_COMMENT')) { $commentTokens[] = T_ML_COMMENT; }
                $tokens = token_get_all($fileStr);
                foreach ($tokens as $token) {    
                    if (is_array($token)) {
                        if (in_array($token[0], $commentTokens)) { continue; }
                        $token = $token[1]; }
                    $newStr .= $token; }
                if (!file_put_contents($id,$newStr)) {
                    $open = fopen($id,"w");
                    fwrite($open,$newStr);
                    fclose($open); }}}}}

rmcomments("path/to/directory");
8
John Tyler

une version plus puissante: supprimez tous les commentaires du dossier

<?php
$di = new RecursiveDirectoryIterator(__DIR__,RecursiveDirectoryIterator::SKIP_DOTS);
$it = new RecursiveIteratorIterator($di);
$fileArr = [];
foreach($it as $file){
    if(pathinfo($file,PATHINFO_EXTENSION) == "php"){
        ob_start();
        echo $file;
        $file = ob_get_clean();
        $fileArr[] = $file;
    }
}
$arr = [T_COMMENT,T_DOC_COMMENT];
$count = count($fileArr);
for($i=1;$i < $count;$i++){
    $fileStr = file_get_contents($fileArr[$i]);
    foreach(token_get_all($fileStr) as $token){
        if(in_array($token[0],$arr)){
            $fileStr = str_replace($token[1],'',$fileStr);
        }            
    }
    file_put_contents($fileArr[$i],$fileStr);
}
3
ZhiJia Tang

Si vous utilisez déjà un éditeur comme UltraEdit , vous pouvez ouvrir un ou plusieurs PHP fichier/s, puis utiliser un Recherche et remplacement simples (CTRL + R) avec l'expression rationnelle Perl suivante

(?s)/\*.*\*/

Attention, l'expression rationnelle ci-dessus supprime également les commentaires à l'intérieur d'une chaîne, c'est-à-dire dans echo "hello/*babe*/"; les /*babe*/ serait également supprimé. Par conséquent, cela pourrait être une solution si vous avez peu de fichiers pour supprimer les commentaires, afin d'être absolument sûr qu'il ne remplace pas à tort quelque chose qui n'est pas un commentaire, vous devrez exécuter la commande Rechercher et remplacer et approuver chaque fois ce qui est remplacé.

2
Marco Demaio
/*
* T_ML_COMMENT does not exist in PHP 5.
* The following three lines define it in order to
* preserve backwards compatibility.
*
* The next two lines define the PHP 5 only T_DOC_COMMENT,
* which we will mask as T_ML_COMMENT for PHP 4.
*/

if (! defined('T_ML_COMMENT')) {
    define('T_ML_COMMENT', T_COMMENT);
} else {
    define('T_DOC_COMMENT', T_ML_COMMENT);
}

/*
 * Remove all comment in $file
 */

function remove_comment($file) {
    $comment_token = array(T_COMMENT, T_ML_COMMENT, T_DOC_COMMENT);

    $input = file_get_contents($file);
    $tokens = token_get_all($input);
    $output = '';

    foreach ($tokens as $token) {
        if (is_string($token)) {
            $output .= $token;
        } else {
            list($id, $text) = $token;

            if (in_array($id, $comment_token)) {
                $output .= $text;
            }
        }
    }

    file_put_contents($file, $output);
}

/*
 * Glob recursive
 * @return ['dir/filename', ...]
 */

function glob_recursive($pattern, $flags = 0) {
    $file_list = glob($pattern, $flags);

    $sub_dir = glob(dirname($pattern) . '/*', GLOB_ONLYDIR);
    // If sub directory exist
    if (count($sub_dir) > 0) {
        $file_list = array_merge(
            glob_recursive(dirname($pattern) . '/*/' . basename($pattern), $flags),
            $file_list
        );
    }

    return $file_list;
}

// Remove all comment of '*.php', include sub directory
foreach (glob_recursive('*.php') as $file) {
    remove_comment($file);
}
1
Steely Wing

Exécutez la commande php --strip file.php dans une invite de commande (ie cmd.exe ), puis accédez à http://www.writephponline.com/phpbeautifier.

Ici, file.php est votre propre fichier.

1

1
Robi Parvez

Solution bash: Si vous souhaitez supprimer récursivement les commentaires de tous les fichiers PHP à partir du répertoire courant, vous pouvez écrire dans le terminal ce one-liner. (Il utilise temp1 fichier à stocker PHP contenu pour le traitement) Notez que cela supprimera tous les espaces blancs avec des commentaires.

 find . -type f -name '*.php' | while read VAR; do php -wq $VAR > temp1  ;  cat temp1 > $VAR; done

Vous devez ensuite supprimer temp1 fichier après.

si PHP_BEAUTIFER est installé alors vous pouvez obtenir du code bien formaté sans commentaires avec

 find . -type f -name '*.php' | while read VAR; do php -wq $VAR > temp1; php_beautifier temp1 > temp2;  cat temp2 > $VAR; done;

puis supprimez deux fichiers (temp1, temp2)

1
Pawel Dubiel

Pour les réponses ajax/json, j'utilise le code PHP code, pour supprimer les commentaires du code HTML/JavaScript, il serait donc plus petit (gain d'environ 15% pour mon code).

// Replace doubled spaces with single ones (ignored in HTML any way)
$html = preg_replace('@(\s){2,}@', '\1', $html);
// Remove single and multiline comments, tabs and newline chars
$html = preg_replace(
    '@(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|((?<!:)//.*)|[\t\r\n]@i',
    '',
    $html
);

Court et efficace, mais peut produire des résultats inattendus si votre code a la syntaxe $ itty.

1
Deele

en 2019 pourrait fonctionner comme ça

<?php
/*   hi there !!!
here are the comments */
//another try

echo removecomments('index.php');

/*   hi there !!!
here are the comments */
//another try
function removecomments($f){
    $w=Array(';','{','}');
    $ts = token_get_all(php_strip_whitespace($f));
    $s='';
    foreach($ts as $t){
        if(is_array($t)){
            $s .=$t[1];
        }else{
            $s .=$t;
            if( in_array($t,$w) ) $s.=chr(13).chr(10);
        }
    }

    return $s;
}

?>

si vous voulez voir les résultats, exécutons-le d'abord dans xampp, puis vous obtenez une page vierge, mais si vous faites un clic droit et cliquez sur voir la source, vous obtenez votre script php .. il se charge et supprime tous les commentaires et aussi les onglets. je préfère aussi cette solution car je l'utilise pour accélérer mon framework un moteur de fichiers "m.php" et après php_strip_whitespace toutes les sources sans ce script que j'observe est le plus lent: j'ai fait 10 benchmarks puis je calcule la moyenne mathématique (je pense php 7 rétablit les manquements cr_lf lors de l'analyse ou prend un certain temps lorsque ceux-ci sont manquants)

0
Constantin

Le hic, c'est qu'un algorithme de correspondance moins robuste (regex simple, par exemple) commencera à se déshabiller ici alors qu'il ne devrait clairement pas:

if (preg_match('#^/*' . $this->index . '#', $this->permalink_structure)) {  

Cela n'affectera peut-être pas votre code, mais finalement, quelqu'un sera mordu par votre script. Vous devrez donc utiliser un utilitaire qui comprend plus la langue que vous ne le pensez.

-Adam

0
Adam Davis

php -w Ou php_strip_whitespace($filename);

documentation

0
Gam Sengie