Sprawdzone metody: praca z długimi, wielowierszowymi ciągami znaków w PHP?


177

Uwaga: przepraszam, jeśli jest to niezwykle proste pytanie, ale mam pewną obsesję kompulsywną w kwestii formatowania mojego kodu.

Mam klasę, która ma funkcję, która zwraca ciąg znaków, który będzie stanowić treść wiadomości e-mail. Chcę, aby ten tekst był sformatowany, aby wyglądał dobrze w e-mailu, ale także, aby mój kod nie wyglądał dziwnie. Oto o co mi chodzi:

class Something
{
    public function getEmailText($vars)
    {
        $text = 'Hello ' . $vars->name . ",

The second line starts two lines below.

I also don't want any spaces before the new line, so it's butted up against the left side of the screen.";
        return $text;
    }
}

ale można go również zapisać jako:

public function getEmailText($vars)
{
    $text = "Hello {$vars->name},\n\rThe second line starts two lines below.\n\rI also don't want any spaces before the new line, so it's butted up against the left side of the screen.";
    return $text;
}

ale o co chodzi z nowymi liniami i powrotami karetki? Co za różnica? Czy \n\njest odpowiednikiem \r\rlub \n\r? Którego należy użyć, gdy tworzę przerwę między wierszami?

Następnie jest opcja buforowania wyjścia i składni heredoc.

Jak sobie radzisz z używaniem długich wielowierszowych ciągów w swoich obiektach?


3
Zawsze myślałem, że \ n to nowa linia w Uniksie \ r to nowa linia w systemie MacOS przed OS / X, a \ r \ n to nowa linia w systemie Windows. Ponadto, biorąc pod uwagę, że będzie to ciąg znaków, który pojawia się w wiadomości e-mail, będziesz chciał się upewnić, że niezależnie od tego, w jaki sposób to robisz, pojawia się poprawnie na większości klientów poczty poleceń. Wskazówka: program Outlook w niektórych przypadkach usuwa dodatkowe znaki nowej linii, więc nie zawsze otrzymasz to, czego oczekujesz.
— Kenny Drobnack

1
Nie jestem pewien, czy to wszystko jest takie ważne, ale pierwotnie dwa znaki „nowego wiersza” pochodziły z fizycznej maszyny do pisania, która używała dwóch znaków. Jeden do umieszczenia karetki z powrotem po lewej stronie strony (CR - 0xD) i taki, który spowodował przejście strony do następnej linii (LF - 0xA). Jestem pewien, że są ludzie, którzy wiedzą więcej na ten temat jednak.
— mkgrunder

Odpowiedzi:


289

Powinieneś użyć HEREDOC lub NOWDOC.

$var = "some text";
$text = <<<EOT
  Place your text between the EOT. It's
  the delimiter that ends the text
  of your multiline string.
  $var
EOT;

Różnica między Heredoc i Nowdoc polega na tym, że kod PHP osadzony w heredoc jest wykonywany, podczas gdy kod PHP w Nowdoc zostanie wydrukowany bez zmian.

$var = "foo";
$text = <<<'EOT'
  My $var
EOT;

W tym przypadku $ text będzie miał wartość My $var.

Uwaga: przed zamknięciem EOT;nie powinno być spacji ani tabulatorów. w przeciwnym razie pojawi się błąd


Czemu? Ponieważ wszystko między pierwszym EOT a drugim jest uważane za ciąg taki, jaki jest. Co oznacza, że ​​nie musisz umieszczać odwrotnego ukośnika n na wszystkich wieloliniowych ciągach. @Fabian: Jaka jest różnica między HEREDOC i NOWDOC, czy też są tym samym?
— Kenny Drobnack

4
@powtac: Nie, ponieważ musi znajdować się w nowej linii, aby zakończyć heredoc. W szczególności musi być EOT;bez spacji przed nim.
— Powerlord

Dodałem wyjaśnienie dla Nowdoc.
— halfdan

6
@halfdan, czy coś mi brakuje? Po co zawracać sobie głowę heredocsami i nowdocs, skoro możemy po prostu wpisać klawisz „Enter” i otoczyć wielowierszowy ciąg cudzysłowami, tak jak zwykły ciąg?
— Pacerier,

3
Po prostu dodaj to do swojej odpowiedzi: przed ostatnią EOT;nie powinno być spacji ani tabulatorów. w przeciwnym razie pojawi się błąd.
— Shnd

44

Używam podobnego systemu co pix0r i myślę, że dzięki temu kod jest całkiem czytelny. Czasami posunąłbym się nawet do oddzielenia podziałów wierszy w podwójnych cudzysłowach i użycia pojedynczych cudzysłowów dla pozostałej części ciągu. W ten sposób wyróżniają się od reszty tekstu, a zmienne również wyróżniają się lepiej, jeśli używasz konkatenacji, zamiast wstawiać je w łańcuch w podwójnym cudzysłowie. Mogę więc zrobić coś takiego na Twoim oryginalnym przykładzie:

$text = 'Hello ' . $vars->name . ','
      . "\r\n\r\n"
      . 'The second line starts two lines below.'
      . "\r\n\r\n"
      . 'I also don\'t want any spaces before the new line,'
      . ' so it\'s butted up against the left side of the screen.';

return $text;

Jeśli chodzi o podziały wierszy, w przypadku e-maili należy zawsze używać \ r \ n. PHP_EOL jest przeznaczone dla plików, które mają być używane w tym samym systemie operacyjnym, w którym działa php.


Czy ustawiłeś to wcięcie w swoim IDE (aby ustawić wielowierszowy ciąg wyrównany do każdej części)?
— Krzysztof Trzos

25

Używam szablonów do długiego tekstu:

email-template.txt zawiera

hello {name}!
how are you? 

W PHP robię to:

$email = file_get_contents('email-template.txt');
$email = str_replace('{name},', 'Simon', $email);

ciekawe ... gdzie przechowujesz swoje szablony w strukturze katalogów aplikacji internetowej?
— Andrew,

Mój kod to tylko demo. W przypadku ogromnej aplikacji internetowej możesz użyć struktury takiej jak / templates / e-mail /, / templates / userfeedback /. Ale jeśli masz więcej rzeczy, poleciłbym pełny system szablonów, taki jak SMARTY.
— powtac

Dwoo dwoo.org to przyzwoity system szablonów PHP zgodny ze SMARTY, który niektórzy uważają za dobrego następcę (zaczął na PHP5, więc nie ma bagażu w PHP4).
— micahwittman

19

Dodawanie \ni / lub \rw środku łańcucha i posiadanie bardzo długiej linii kodu, jak w drugim przykładzie, nie wydaje się właściwe: kiedy czytasz kod, nie widzisz wyniku i musisz przewijać .

W tego rodzaju sytuacjach zawsze używam Heredoc (lub Nowdoc, jeśli używam PHP> = 5.3) : łatwe do napisania, łatwe do odczytania, nie ma potrzeby stosowania bardzo długich wierszy, ...

Na przykład :

$var = 'World';
$str = <<<MARKER
this is a very
long string that
doesn't require
horizontal scrolling, 
and interpolates variables :
Hello, $var!
MARKER;

Tylko jedno: znacznik końcowy (i „ ;” po nim) musi być jedyną rzeczą w tym wierszu: bez spacji / tabulacji przed ani po!


12

Jasne, możesz użyć HEREDOC, ale jeśli chodzi o czytelność kodu, nie jest to tak naprawdę lepsze niż pierwszy przykład, zawijając ciąg w wiele linii.

Jeśli naprawdę chcesz, aby Twój wieloliniowy ciąg wyglądał dobrze i dobrze płynął z Twoim kodem, polecam łączenie ciągów w taki sposób:

$text = "Hello, {$vars->name},\r\n\r\n"
    . "The second line starts two lines below.\r\n"
    . ".. Third line... etc";

Może to być nieco wolniejsze niż HEREDOC lub ciąg wieloliniowy, ale będzie dobrze płynąć z wcięciem twojego kodu i ułatwi czytanie.


9

Trochę bardziej podoba mi się ta metoda w Javascript, ale wydaje się, że warto ją tutaj uwzględnić, ponieważ nie została jeszcze wspomniana.

$var = "pizza";

$text = implode(" ", [
  "I love me some",
  "really large",
  $var,
  "pies.",
]);

// "I love me some really large pizza pies."

W przypadku mniejszych rzeczy często łatwiej jest pracować ze strukturami tablicowymi w porównaniu z połączonymi ciągami.

Powiązane: implode vs concat performance


1

Ten, który w to wierzy

"abc\n" . "def\n"

czy ciąg wielowierszowy jest nieprawidłowy. To dwa łańcuchy z operatorem konkatenacji, a nie ciąg wielowierszowy. Takich połączonych ciągów nie można na przykład używać jako kluczy predefiniowanych tablic. Niestety php nie oferuje prawdziwych ciągów wielowierszowych w postaci

"abc\n"
"def\n"

tylko HEREDOCi NOWDOCskładnię, która jest bardziej odpowiednia dla szablonów, ponieważ zagnieżdżone wcięcie kodu jest łamane przez taką składnię.


1

możesz także użyć:

<?php
ob_start();
echo "some text";
echo "\n";

// you can also use: 
?> 
some text can be also written here, or maybe HTML:
<div>whatever<\div>
<?php
echo "you can basically write whatever you want";
// and then: 
$long_text = ob_get_clean();

0

Jeśli chodzi o pytanie dotyczące nowych linii i zwrotów karetek:

Zalecałbym użycie predefiniowanej globalnej stałej PHP_EOL, ponieważ rozwiąże ona wszelkie problemy ze zgodnością między platformami.

To pytanie zostało zadane wcześniej w SO i możesz uzyskać więcej informacji, czytając „ Kiedy używam stałej PHP PHP_EOL ”


1
Komentarz do tej odpowiedzi sugeruje, że powinienem używać \ r \ n do nowych wierszy w wiadomościach e-mail: stackoverflow.com/questions/128560/ ...
— Andrew

0

ale o co chodzi z nowymi liniami i powrotami karetki? Co za różnica? Czy \ n \ n jest odpowiednikiem \ r \ r lub \ n \ r? Którego należy użyć, gdy tworzę przerwę między wierszami?

Nikt tutaj chyba nie odpowiedział na to pytanie, więc oto jestem.

\r reprezentuje „powrót karetki”

\n reprezentuje „wysuw o wiersz”

Rzeczywista przyczyna ich powstania sięga maszyn do pisania. W miarę wpisywania tekstu „karetka” przesuwał się powoli, znak po znaku, na prawo od maszyny do pisania. Gdy dojdziesz do końca linii, wrócisz karetką, a następnie udasz się do nowej linii . Aby przejść do nowego wiersza, należy przesunąć dźwignię, która podawała wiersze pisarzowi. W związku z tym te działania, łącznie, nazwano wysuwem wiersza powrotu karetki . A więc dosłownie:

Kanał linia, \noznacza przejście do następnej linii.

Powrót karetki \roznacza przesunięcie kursora na początek wiersza.

Ostatecznie Hello\n\nWorldna ekranie powinien pojawić się następujący wynik:

Hello

     World

Gdzie Hello\r\rWorldpowinno skutkować następującym wyjściem .

Dopiero łącząc te 2 znaki \r\n, masz wspólne rozumienie znanej linii. IE Hello\r\nWorldpowinno skutkować:

Hello
World

I oczywiście \n\rdałoby taki sam efekt wizualny jak \r\n.

Pierwotnie komputery brały \ri \ndosłownie. Jednak w dzisiejszych czasach poparcie dla powrotu karetki jest niewielkie. Zwykle w każdym systemie możesz uciec z \nsamodzielnym używaniem . To nigdy nie zależy od systemu operacyjnego, ale zależy od tego, w czym przeglądasz dane wyjściowe.

Mimo to zawsze radziłbym używać, \r\ngdzie tylko możesz!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.