[PHP] Kan niet exploden op "\n"

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Soms zijn de meest eenvoudige dingen onwaarschijnlijk lastig. Ik heb een Parser class en een Email class. De Email class accepteert output van de Parser class, die een template file inleest (fgets) en verwerkt.

Nou wil ik die output van de Parser class "exploden" op newline karakters.

Parser.php (relevante code)
PHP:
1
2
3
4
5
6
$handle = fopen($path, "r");
while (!feof($handle)) {
    $buffer[] = fgets($handle, 4096);
}
fclose($handle);
$this->subject = implode("", $buffer);


Email.php (relevante code)
PHP:
1
$content = explode("\n", $content);


De bovenstaande explode werkt niet. Toch zijn er wel degelijk newline karakters aanwezig, want met nl2br() wordt iedere regel netjes voorzien van een <br />. Ik kan zat work-arounds verzinnen, maar ik hoop eigenlijk de oorzaak te achterhalen. Suggesties zijn van harte welkom, Google, GoT search en de almachtige PHP manual konden me niet helpen...

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Waarom gebruik je niet gewoon de functie file? ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb ze allemaal geprobeerd (ook file_get_contents), maar ik las ergens dat fgets qua performance (bij grotere bestanden) efficiënter was :)

[edit] Ik begrijp nu pas dat je bedoelt file() te gebruiken, i.p.v. naderhand weer te converteren naar een array. Dat gaat niet omdat de Parser class zijn parses uitvoert op een string ($subject) en die via de &get() accessor teruggeeft. In de Email class moet ik echter een array hebben en geen string.

[ Voor 52% gewijzigd door Verwijderd op 20-05-2005 23:45 ]


Acties:
  • 0 Henk 'm!

  • Scott
  • Registratie: December 2004
  • Laatst online: 20-09 21:57

Scott

Ik ben, dus ik tweak

Probeer het dan eens zo:

PHP:
1
$content = explode('\n', $content);


Het kan zijn dat PHP \n in explode daadwerkelijk parst, terwijl het in de variabele waar het bestand in staat dan plain is :)

Acties:
  • 0 Henk 'm!

  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 29-05 01:29
je bent ook wel een lekkere......... van een string ga je naar een array met die explode.

Wat als je er een andere var aan hangt? (want ik vind het maar scary dat je zo enorm misbruik maakt van de eh, hoe heet dat, loose typing?)

vardumpjes en print_r's van het resultaat levert ook niks nuttigs op?

en anders moet je misschien de \n escapen? of iets met regexp's doen...... of misschien moet je \n converteren naar char(13) ofzo...... voordat je het kan exploden... (ergo: ik weet het ook niet precies, en opper maar wat ideeen in de rondte)


scottb: owja, subtiele ' ' vs " " perikelen is ook wel een idee ja. goeie (naja, in een (ba)sh werkt het wel zo irritant met die ' en " )

[ Voor 13% gewijzigd door cavey op 20-05-2005 23:45 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Wanneer je file gebruikt, dan staat alles meteen al in een array, dus dan hoef je niet te exploden. Kun je dat niet gebruiken dan?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
ScottB schreef op vrijdag 20 mei 2005 @ 23:42:
Het kan zijn dat PHP \n in explode daadwerkelijk parst, terwijl het in de variabele waar het bestand in staat dan plain is :)
Als het er plain zou staan, is het "\\n", en dat lijkt me niet het geval.

De code die de TS postte heb ik trouwens met een lokaal bestand getest, en daarbij werkte het zoals verwacht (komt een array uit met elke regel als apart element).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ScottB schreef op vrijdag 20 mei 2005 @ 23:42:
Het kan zijn dat PHP \n in explode daadwerkelijk parst, terwijl het in de variabele waar het bestand in staat dan plain is :)
Werkt helaas ook niet. Bovendien moet PHP de \n juist intern parsen, omdat het immers ook niet letterlijk in de $content staat, toch?

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

komakeef schreef op vrijdag 20 mei 2005 @ 23:44:
je bent ook wel een lekkere......... van een string ga je naar een array met die explode.
Dat lijkt me precies wat hij wil? :P
Wat als je er een andere var aan hangt? (want ik vind het maar scary dat je zo enorm misbruik maakt van de eh, hoe heet dat, loose typing?)
Misbruik? Hij weet toch dat het een string is? ;)
en anders moet je misschien de \n escapen? of iets met regexp's doen...... of misschien moet je \n converteren naar char(13) ofzo...... voordat je het kan exploden... (ergo: ik weet het ook niet precies, en opper maar wat ideeen in de rondte)
\n is al geëscaped, er staat niet voor niks een \ voor. ;) Eventueel zou TS kunnen kijken naar preg_split, maar met explode moet het ook werken, al zou ik liever gewoon de file-functie gebruiken.
scottb: owja, subtiele ' ' vs " " perikelen is ook wel een idee ja. goeie (naja, in een (ba)sh werkt het wel zo irritant met die ' en " )
Voor zover ik weet maken enkele/dubbele quotes voor dit soort karakters niet uit. Sowieso wordt tussen dubbele quotes normaal juist meer geparset, dus dat kan het niet zijn volgens mij. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
GlowMouse schreef op vrijdag 20 mei 2005 @ 23:47:
[...]
De code die de TS postte heb ik trouwens met een lokaal bestand getest, en daarbij werkte het zoals verwacht (komt een array uit met elke regel als apart element).
Huh? Zelfs met file() of file_get_contents()?

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op vrijdag 20 mei 2005 @ 23:50:
[...]


Huh? Zelfs met file() of file_get_contents()?
Het lijkt me dat het om jouw exacte code gaat. ;)

Wat heb je zelf dan voor idee van wat explode moet doen? explode neemt een string, en converteert die naar een array. In jouw geval met één element per regel. En hetzelfde krijg je ook als je gewoon meteen je file inleest met de file-functie.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Het komt erop neer dat ik het spoor volledig kwijt ben...

Volgens preg_replace() en explode() is er in $content geen \n te bekennen, maar nl2br() doet wel netjes wat je ervan verwacht. Hieronder wat meer code, misschien zie ik iets over het hoofd:

PHP:
1
2
3
4
5
6
7
$Email  = &new Email();
$Parser = &new Parser();
$Parser->loadTemplate("/email/register.tmpl");
$Parser->parse($templateData);
$Email->setContent($Parser->get());
$Email->addReciptient($emailAddress);
$Email->send();


Parser.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    class Parser {
        private $subject;
        
        public function __construct() {
        }
        
        public function &get() {
            return $this->subject;
        }
        
        public function loadTemplate($path) {
            $path = TEMPLATE_ROOT . $path;
            if(file_exists($path)) {
                $this->subject = implode("", file($path));
            } else {
                die("Failed to load template: " . $path);
            }
        }
        
        public function parse($templateData) {
            foreach($templateData as $name => $value) {
                $what[] = "/\{$name\}/";
                $with[] = $value;
            }
            $this->subject = preg_replace($what, $with, $this->subject);
        }
        
        public function setSubject($subject) {
            $this->subject = $subject;
        }
    }


Email.php
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    class Email {
        private $body;
        private $from;
        private $hideReciptients;
        private $subject;
        private $reciptient;
        
        public function __construct($hideReciptients = false) {
            $this->hideReciptients = $hideReciptients;
        }
        
        public function addReciptient($emailAddress) {
            $this->reciptient[] = $emailAddress;
        }
        
        public function setContent($content) {
            $content2 = explode("\n", $content);
            echo "<pre>";
            print_r($content2);
            echo "</pre>";
        }
        
        public function send() {
            $to = rtrim(implode(", ", $this->reciptient), ", ");
            
            if($this->hideReciptients) {
                $bcc    = $to;
                $to     = "";
            } else {
                $bcc    = "";
            }

            mail($to, $this->subject, $this->body,
                "bcc: $bcc\r\n" .
                "from: noreply@greatgoodplace.net <Greatgoodplace.net>\r\n" .
                "x-mailer: PHP/" . phpversion());
            echo "<strong>$this->subject</strong><br /><br />$this->body";
            exit;
        }
    }

[ Voor 9% gewijzigd door Verwijderd op 20-05-2005 23:59 ]


Acties:
  • 0 Henk 'm!

  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 29-05 01:29
-NMe- schreef op vrijdag 20 mei 2005 @ 23:50:

[...]

Misbruik? Hij weet toch dat het een string is? ;)
ja ik bedoelde meer van je hebt een $content-string en je maakt er een $content-array van.
zelfde var namen.. loose typing, implicit conversie van type string naar type array....... niet dat hij er een andere type var in de explode aanroep zou stoppen.

en ja hmm, \n is al escaped idd........ 8)7 ik beroep me op sed-bash/zsh ellende waar ik constant aan het \\\\\\\\\'n ben :P

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
Verwijderd schreef op vrijdag 20 mei 2005 @ 23:28:
Parser.php (relevante code)
PHP:
1
2
3
4
5
6
$handle = fopen($path, "r");
while (!feof($handle)) {
    $buffer[] = fgets($handle, 4096);
}
fclose($handle);
$this->subject = implode("", $buffer);
Dat is natuurlijk een tamelijk inefficiente manier van werken, eerst een array maken en dat imploden naar een string.
Waarom doe je niet $this->subject = ''; en in je while $this->subject .= fgets(...);

En als je het later toch explode, waarom dan eerst de implode?
De bovenstaande explode werkt niet.
Ik ben er vrij zeker van dat bovenstaande explode wél werkt, maar ik vermoed dat je verkeerd test of de output verkeerd interpreteert.

Toch zijn er wel degelijk newline karakters aanwezig, want met nl2br() wordt iedere regel netjes voorzien van een <br />.

Ik zie niet in wat nl2br hiermee te maken heeft? Je weet toch dat nl2br de newline-tekens in een tekst aanvult met een br-tag? Maar waarom zouden er newlines in moeten zitten omdat nl2br ermee gewerkt heeft? Want als er op voorhand geen newline in zat (zelfs als er wel br-tags inzaten) zitten er na nl2br echt niet ineens wel newlines in hoor...

[ Voor 3% gewijzigd door ACM op 21-05-2005 00:08 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ACM schreef op zaterdag 21 mei 2005 @ 00:02:
Ik zie niet in wat nl2br hiermee te maken heeft? Je weet toch dat nl2br de newline-tekens in een tekst aanvult met een br-tag? Maar waarom zouden er newlines in moeten zitten omdat nl2br ermee gewerkt heeft? Want als er op voorhand geen newline in zat (zelfs als er wel br-tags inzaten) zitten er na nl2br echt niet ineens wel newlines in hoor...
Dat de tekst NA nl2br <br />'s bevat, betekent dat er newlines zijn gevonden en aangevuld met <br />, terwijl de overige functies (explode, preg_replace) überhaupt geen newlines vinden.

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
PHP:
1
$this->subject = implode("", file($path));

Kun je dat niet makkelijker met file_get_contents doen?

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
Verwijderd schreef op zaterdag 21 mei 2005 @ 00:06:
Dat de tekst NA nl2br br />'s bevat, betekent dat er newlines zijn gevonden en aangevuld met br />, terwijl de overige functies (explode, preg_replace) überhaupt geen newlines vinden.
Nee, dat betekent dat er regeleindes gevonden zijn (voor Mac dus evt \r). Ben je er trouwens zeker van dat die br's er voor je conversie niet ook al inzaten?
Als de overige functies geen \n (tussen "") kunnen vinden, dan zaten die er ook echt niet in.

Doe maar eens op de initiele inhoud van die file:
PHP:
1
echo str_replace(array("\r", "\n"), array('\r', '\n'), $data);


Als er na die str_replace geen \n's opduiken, dan zaten ze er niet in. Dan kan nl2br ook nooit wél \n's gevonden hebben.

[ Voor 19% gewijzigd door ACM op 21-05-2005 00:12 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
In het PHP manual staat (bij file):

"Note: If you are having problems with PHP not recognizing the line endings when reading files either on or created by a Macintosh computer, you might want to enable the auto_detect_line_endings run-time configuration option."

Ik zit dus te programmeren op een PowerBook en ik sla met zelf voor m'n kop als het hier iets mee te maken heeft...

[edit] In de AMFPHP (voor Flash <-> PHP/MySQL) documentatie las ik ergens al iets dat je je Dreamweaver newlines op LF (Unix) moest zetten. Dat heb ik bij deze gedaan en de templates opnieuw opgeslagen. Nu werkt alles prima.

/me pakt een plank met een roestige spijker en slaat zichzelf in het gezicht.

[ Voor 31% gewijzigd door Verwijderd op 21-05-2005 00:15 ]


Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
Ja dus... Mac eindigt met \r en gebruikt de \n helemaal niet, zoals ik al eerder suggereerde

[ Voor 22% gewijzigd door ACM op 21-05-2005 00:12 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
ACM schreef op zaterdag 21 mei 2005 @ 00:12:
Ja dus... Mac eindigt met \r en gebruikt de \n helemaal niet, zoals ik al eerder suggereerde
Je hebt helemaal gelijk. Nooit geweten. Bedankt voor deze les, hopelijk heeft dit topic nog nut voor andere Mac coders die tegen hetzelfde probleem aanlopen.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op zaterdag 21 mei 2005 @ 00:16:
[...]


Je hebt helemaal gelijk. Nooit geweten. Bedankt voor deze les, hopelijk heeft dit topic nog nut voor andere Mac coders die tegen hetzelfde probleem aanlopen.
Let je wel op dat als je weer alleen op \r gaat exploden, je script dan niet meer werkt in Linux, en in Windows vreemd gaat doen? (Windows gebruikt \r\n als regeleinde, wat dus betekent dat de "enter" blijft staan als je de \r weghaalt.)

Maar daar zou je geen problemen mee moeten krijgen als je gewoon de file-functie werkend krijgt. :)

[ Voor 10% gewijzigd door NMe op 21-05-2005 00:29 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
-NMe- schreef op zaterdag 21 mei 2005 @ 00:28:
[...]
Maar daar zou je geen problemen mee moeten krijgen als je gewoon de file-functie werkend krijgt. :)
Ik heb het al opgelost door Dreamweaver (Mac) zo in te stellen dat-ie \n voor newlines gebruikt i.p.v. \r. Altijd de oorzaak aanpakken ;)

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

(jarig!)
Je kan natuurlijk ook voor de zekerheid alle line-endingcombinaties pakken met een preg_split:
PHP:
1
$array = preg_split("/\r|\n|\r\n/", $input);


Of gewoon niet je strings imploden maar de array die je met fgets creeert (of met file() ) direct toepassen.
Pagina: 1