web-dev-qa-db-fra.com

Nouvelle ligne à la fonction de paragraphe

J'ai cette fonction intéressante que j'utilise pour créer de nouvelles lignes dans les paragraphes. Je l'utilise à la place de la fonction nl2br (), car elle génère un texte mieux formaté. 

function nl2p($string, $line_breaks = true, $xml = true) {

$string = str_replace(array('<p>', '</p>', '<br>', '<br />'), '', $string);

// It is conceivable that people might still want single line-breaks
// without breaking into a new paragraph.
if ($line_breaks == true)
    return '<p>'.preg_replace(array("/([\n]{2,})/i", "/([^>])\n([^<])/i"), array("</p>\n<p>", '<br'.($xml == true ? ' /' : '').'>'), trim($string)).'</p>';
else 
    return '<p>'.preg_replace(
    array("/([\n]{2,})/i", "/([\r\n]{3,})/i","/([^>])\n([^<])/i"),
    array("</p>\n<p>", "</p>\n<p>", '<br'.($xml == true ? ' /' : '').'>'),

    trim($string)).'</p>'; 

}

Le problème est que chaque fois que j'essaie de créer un seul saut de ligne, il supprime par inadvertance le premier caractère du paragraphe en dessous. Je ne suis pas assez familier avec regex pour comprendre ce qui cause le problème. 

Toute aide que vous pouvez offrir est grandement appréciée. 

25
Jeremy

Le problème vient de votre correspondance pour les sauts de ligne simples. Il correspond au dernier caractère avant le saut de ligne et au premier après. Ensuite, vous remplacez la correspondance par <br>, de sorte que vous perdez également ces caractères. Vous devez les garder dans le remplacement.

Essaye ça:

function nl2p($string, $line_breaks = true, $xml = true) {

$string = str_replace(array('<p>', '</p>', '<br>', '<br />'), '', $string);

// It is conceivable that people might still want single line-breaks
// without breaking into a new paragraph.
if ($line_breaks == true)
    return '<p>'.preg_replace(array("/([\n]{2,})/i", "/([^>])\n([^<])/i"), array("</p>\n<p>", '$1<br'.($xml == true ? ' /' : '').'>$2'), trim($string)).'</p>';
else 
    return '<p>'.preg_replace(
    array("/([\n]{2,})/i", "/([\r\n]{3,})/i","/([^>])\n([^<])/i"),
    array("</p>\n<p>", "</p>\n<p>", '$1<br'.($xml == true ? ' /' : '').'>$2'),

    trim($string)).'</p>'; 
}
40

Voici une autre approche qui n'utilise pas d'expressions régulières. Notez que cette fonction supprimera tout saut de ligne.

function nl2p($string)
{
    $paragraphs = '';

    foreach (explode("\n", $string) as $line) {
        if (trim($line)) {
            $paragraphs .= '<p>' . $line . '</p>';
        }
    }

    return $paragraphs;
}

Si vous n'avez besoin de faire cela qu'une seule fois dans votre application et que vous ne voulez pas créer de fonction, vous pouvez facilement le faire en ligne:

<?php foreach (explode("\n", $string) as $line): ?>
    <?php if (trim($line)): ?>
        <p><?=$line?></p>
    <?php endif ?>
<?php endforeach ?>
36
Jonathan

J'ai aussi écrit une version très simple:

function nl2p($text)
{
    return '<p>'.str_replace(array("\r\n", "\r", "\n"), '</p><p>', $text).'</p>';
}
5
NaturalBornCamper

La réponse de @ Laurent ne fonctionnait pas pour moi. L'instruction else faisait ce que l'instruction $line_breaks == true aurait dû faire, et elle effectuait plusieurs sauts de ligne dans les balises <br>, ce que fait déjà nl2br() de PHP.

Voici ce que j'ai réussi à faire avec le comportement attendu:

function nl2p( $string, $line_breaks = true, $xml = true ) {

    // Remove current tags to avoid double-wrapping.
    $string = str_replace( array( '<p>', '</p>', '<br>', '<br />' ), '', $string );

    // Default: Use <br> for single line breaks, <p> for multiple line breaks.
    if ( $line_breaks == true ) {
        $string = '<p>' . preg_replace(
            array( "/([\n]{2,})/i", "/([\r\n]{3,})/i", "/([^>])\n([^<])/i" ),
            array( "</p>\n<p>", "</p>\n<p>", '$1<br' . ( $xml == true ? ' /' : '' ) . '>$2' ),
            trim( $string ) ) . '</p>';

    // Use <p> for all line breaks if $line_breaks is set to false.
    } else {
        $string = '<p>' . preg_replace(
            array( "/([\n]{1,})/i", "/([\r]{1,})/i" ),
            "</p>\n<p>",
            trim( $string ) ) . '</p>';
    }

    // Remove empty paragraph tags.
    $string = str_replace( '<p></p>', '', $string );

    // Return string.
    return $string;

}
1
Shoelaced

Voici une approche qui inclut une méthode inverse pour remplacer les paragraphes par des sauts de ligne réguliers et inversement. 

Celles-ci sont utiles à utiliser lors de la création d'une entrée de formulaire. Lorsque vous enregistrez une entrée utilisateur, vous pouvez convertir les sauts de ligne en balises de paragraphe. Toutefois, lors de la modification du texte d'un formulaire, vous pouvez empêcher l'utilisateur de voir des caractères HTML. Ensuite, nous remplacerions les paragraphes à la ligne.

// This function will convert newlines to HTML paragraphs
// without paying attention to HTML tags. Feed it a raw string and it will
// simply return that string sectioned into HTML paragraphs
function nl2p($str) {
    $arr=explode("\n",$str);
    $out='';

    for($i=0;$i<count($arr);$i++) {
        if(strlen(trim($arr[$i]))>0)
            $out.='<p>'.trim($arr[$i]).'</p>';
    }
    return $out;
}

// Return paragraph tags back to line breaks
function p2nl($str)
{
    $str = preg_replace("/<p[^>]*?>/", "", $str);
    $str = str_replace("</p>", "\r\n", $str);
    return $str;
}
1
internet-nico