PHPhil's Playground http://phphil.ch/index.php Ein deutscher Blog über Webprogrammierung, Webdesign und das Leben als Held de Copyleft - All Rites Reversed Wed, 10 Mar 2010 14:59:05 +0100 WPA Key mit Sonderzeichen unter Ubuntu Das Einrichten eines WLANs mit einem WPA Key mit Umlauten unter Ubuntu machte mir kürzlich zu schaffen. Das Problem: Die Zeichenkodierung. Die Lösung: Gibt's hier! <p><strong>Das Einrichten eines WLANs mit einem WPA Key mit Umlauten unter Ubuntu machte mir kürzlich zu schaffen. Das Problem: Die Zeichenkodierung. Die Lösung: Gibt's hier!</strong></p><p>Nehmen wir an, ich m&ouml;chte folgendes drahtlose Netzwerk einrichten:</p> <p style="padding-left: 30px;">SSID: <code>BlindMelon</code><br />WPA Key: <code>SieSagenDieGr&ouml;sseSpieleKeineRolle</code></p> <p>So weit ich das Problem verstanden habe, liegt der Fehler dort, dass die meisten Router nocht mit ISO 8859-1 arbeiten, Ubuntu aber standardm&auml;ssig mit UTF-8. Dadurch wird der von Hand eingegebene Key aber falsch &uuml;bermittelt.</p> <p>Die L&ouml;sung liegt darin, dass anstelle des lesbaren Keys auch ein 64-stelliger Hexstring genutzt werden kann. Um diesen zu berechnen kann man unter Ubuntu das kleine CLI-Tool <code>wpa_passphrase</code> nutzen.</p> <p>Und so funktionierts ...</p> <ol> <li>Wir &ouml;ffnen erstmal ein Terminal.</li> <li>Danach setzen wir das Encoding des Terminals auf ISO 8859-1.</li> <li>Anschliessen tippen wir <code>wpa_passphrase BlindMelon </code><code>SieSagenDieGr&ouml;sseSpieleKeineRolle</code> ein und erhalten folgende Ausgabe:<br /><code><br />network={<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssid="BlindMelon"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #psk="SieSagenDieGr&ouml;sseSpieleKeineRolle"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; psk=b9a67b4c042a391fc44ba8ad81c2010d41bf699cd5c5f95a60056fda58724ead<br />}<br /><br /></code></li> <li>Die Zeile mit <code>psk=b9a...</code> ist nun der Key von Interesse und welchen wir anstelle des lesbaren Keys verwenden k&ouml;nnen.</li> </ol> http://bigwhoop.ch/artikel/44/2009-02-11/WPA-Key-mit-Sonderzeichen-unter-Ubuntu info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/44/2009-02-11/WPA-Key-mit-Sonderzeichen-unter-Ubuntu Wed, 11 Feb 2009 10:45:21 +0100 Die Ethik der Programmierer Brandon Savage griff soeben ein sehr interessantes Thema in seinem Blog auf: Inwiefern werden die Moralvorstellungen von Programmieren gewertet und beachtet? <p><strong>Brandon Savage griff soeben ein sehr interessantes Thema in seinem Blog auf: Inwiefern werden die Moralvorstellungen von Programmieren gewertet und beachtet?</strong></p><p>Zuerst m&ouml;chte ich das Thema von Programmierern auf einen speziellen Teil der IT ausweiten: Die geliebten Sysadmins.</p> <p>Aus Erfahrung haben Mitarbeiter der IT grunds&auml;tzlich mehr Zugriffsrechte als normale Angestellte. Diese Rechte beziehen sich nicht nur auf "digitale Rechte", sondern z.B. auch auf Zugang zu Bereichen des Firmengel&auml;ndes. Wie soll ein Router gewartet werden, wenn der Techniker keinen Zutritt hat?! Ausserdem haben IT-Mitarbeiter in der Regel Zugriff auf&nbsp; sehr sensible Daten: Buchhaltung, Passw&ouml;rter, E-Mails, etc. Programmierer bringen desweiteren eine grosse Verantwortung mit, wenn sie mit diesen Daten etwas machen sollen. Unsichere Software kann da schon mal gesch&auml;ftskritisch sein.</p> <p>Bei meinem letzten Arbeitgeber wurde eine Buchhalterin per sofort freigestellt, als man sich entschloss, das Arbeitsverh&auml;ltnis aufzul&ouml;sen. Ich lies mir sagen, dass dies in solch kritischen Gesch&auml;ftsbereichen normal ist. Gleichzeitig musste ich aber auch die Stirn runzeln und mich selbst fragen: "Wissen die da oben &uuml;berhaupt, welches Wissen und welche "Macht" ich habe oder ohne weiteres erlangen kann?"</p> <p>Die Frage ist jetzt, ob sich Firmen dieses Risikos nicht bewusst sind, nichts dagegen unternehmen wollen oder schlicht damit Leben m&uuml;ssen? Da mich letzteres schockieren w&uuml;rde tippe ich trotz meiner relativ kurzen Berufserfahrung auf ersteres und hoffe, dass sich dieser Umstand in Zukunft &auml;ndern wird.</p> <p>Brandon Savage bedauert in <a class="DefaultLink" href="http://www.brandonsavage.net/ethics-for-programmers/" target="_blank">seinem Post</a> vor allem, dass Programmierer im Gegensatz zu anderen Branchen kaum auf Ethik geschult werden und es keine Richtlinien gibt. Dies kann ich so nat&uuml;rlich nur unterschreiben.</p> http://bigwhoop.ch/artikel/40/2009-08-13/Die-Ethik-der-Programmierer info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/40/2009-08-13/Die-Ethik-der-Programmierer Thu, 13 Aug 2009 00:39:36 +0200 Wie ich Zend Certified Engineer wurde (mit Gewinnspiel) Zugegeben, der Titel klingt etwas hochgestochen, doch möchte ich in diesem Artikel nur kurz meine Erfahrungen und meine Vorgehensweise auf dem Weg zum Zend Certified Engineer weitergeben. <p><strong>Zugegeben, der Titel klingt etwas hochgestochen, doch möchte ich in diesem Artikel nur kurz meine Erfahrungen und meine Vorgehensweise auf dem Weg zum Zend Certified Engineer weitergeben.</strong></p><h2>Mein Vorwissen</h2> <p>Zur Zeit bin ich 22 Jahre alt. Angefangen PHP zu programmieren habe ich irgendwann zwischen 2001 und 2002, also mit etwa 14/15 Jahren. Es m&uuml;sste demnach eine 4.1.x Version von PHP gewesen sein. Ziemlich lange war dieses Interesse aber sehr oberfl&auml;chlich. W&auml;hrend meiner Ausbildung lernte ich vor allem ASP und C++, wodurch PHP zum Hobby verkam. Nach der Ausbildung und w&auml;hrend meiner ersten beruflichen T&auml;tigkeit begann das Interesse an PHP zu wachsen. Gr&uuml;nde waren die tollen, neuen M&ouml;glichkeiten von PHP 5 und die Tatsache, dass es mein damaliger Arbeitgeber verpasste von ASP (in meinen Augen einfach nur eine Zangengeburt) auf ASP.NET zu wechseln. Unterm Strich war PHP einfach anwenderfreundlich, leistungsstark und ... gratis!</p> <p>Zwar kannte ich objektorientierte Programmierung aus C++ etwas, einen tieferen Einblick erlangte ich aber erst mit PHP 5(.1). In dieser Zeit begann ich auch mich vermehrt mit weiterf&uuml;hrenden Themen der Programmierung zu befassen: Design Patterns (MVC, ARP), Security, Caching, usw.</p> <p>Von Sommer 2007 an arbeitete ich dann zwei Jahre bei einem Arbeitgeber wo ich endlich PHP beruflich programmieren konnte. Durch ein sehr abwechslungsreiches und grosses Projekt und dank meines direkten Mitarbeiters im Backend-Bereich, der mich st&auml;ndig mitzog, konnte ich sehr, sehr viel lernen. Ich lernte das Zend Framework kennen (und damit viele gute Ans&auml;tze in Sachen Webdevelopment), Propel ORM und vor allem all die kleinen Dinge die man nicht auflisten kann. In meiner Freizeit besch&auml;ftigte ich mich ebenfalls stetig mit dem gesamten Spektrum von <a class="DefaultLink" href="http://de.wikipedia.org/wiki/Webwork" target="_blank">Webwork</a> und versuchte mich stetig weiterzuentwicklen.</p> <p style="font-weight : bold;">Zusammenfassend hatte ich ein gutes, umfassendes Vorwissen in PHP und vor allem OOP (in PHP). Wegen der Benutzung von Fremdbibliotheken und Frameworks und der dahingehenden Abstraktion verlor ich mit der Zeit aber etwas den Bezug zu den Basics. Als Beispiel nenne ich da jetzt mal die mysql_*- oder neueren mysqli_*-Funktionen (PDO ist eh das einzige Wahre :P).</p> <h2>Meine Vorbereitung</h2> <p>Anfangs 2009 spielte ich erstmals mit dem Gedanken die Zend Zertifizierung zu machen. Dieser Gedanke wurde aber nie richtig konkret und so ging er in Vergessenheit. Per Ende Juni k&uuml;ndigte ich dann meine damalige Arbeitsstelle und die Idee zur Zertifizierung kam zwecks Stellensuche und sinnvoller Freizeitgestaltung wieder auf.</p> <p>Zuerst begann ich im Internet nach Erfahrungsberichten zu suchen. Diese beinhalteten allerdings meisten nur den Tipp, einfach das PHP Manual Wort f&uuml;r Wort zu lesen. So bl&ouml;d es klingt, dieser Tipp ist in der Tat der beste, um sich das am Testtag gefragte Wissen &uuml;ber PHP anzueignen. Wie sinnvoll dieses Wissen ist, sei dahingestellt. Es ist aber durchaus von Vorteil wenn man z.B. weiss in welcher Reihenfolge bei bekannten String-Funktionen die Parameter erwartet werden oder wann und wie PHP die Datentypen dynamisch wechselt. Viel dieses Wissens ist in der Praxis nicht wirklich von N&ouml;ten, da man z.B. dank Autocomplete nicht alle Funktionen auswendig kennen muss und schon gar nicht, in welcher Reihenfolge die Argumente erwartet werden (PHP ist da ja nicht gerade sehr konsistent).</p> <p style="font-weight : bold;">Dennoch: Manual gut lesen! Man muss die Stream-Funktionen kennen, das PHP 5 OO Model, die Unterschiede zwischen PHP 4 und 5, all die verschiedenen XML Parser und vor allem die gesamten Basics wie Syntax, Datentypen (Arrays!), usw.</p> <p>Damit ich mir ein Bild machen konnte wie die Pr&uuml;fung abl&auml;uft, kaufte ich zehn ZCE Mock Exams (f&uuml;nf davon habe ich noch und werde sie am Ende dieses Artikels als kleines Gewinnspiel ausschreiben). Der Test findet am Computer statt und man wird mit Single Choice-, Multiple Choice- und Freetext-Fragen konfrontiert. Bei Multiple Choice-Fragen steht jeweils wie viele Antworten erwartet werden und bei den Freetext-Aufgaben muss man jeweils nur ein Wort schreiben, z.B. "Singleton". Der Test besteht aus 70 Fragen, wof&uuml;r man 90 Minuten Zeit hat. Man kann jede Frage am Ende des Tests nochmals &ouml;ffnen und &auml;ndern.</p> <p>Diese Probeexamen lernten mich vor allem eines: Man muss an das Undenkbare denken! Es werden Fragen gestellt, die auf absichtlichem Missbrauch von PHP basieren. Ausserdem halfen mir die Teste mich besser auf meine Schw&auml;chen konzentrieren zu k&ouml;nnen und sie gaben mir auch immer wieder Schlagw&ouml;rter, die mich zu neuen Erkenntnissen f&uuml;hrten. Zum Beispiel "Cross-Site Request Forgery". Ein paar <a class="DefaultLink" href="http://bigwhoop.ch/artikel/28/2009-07-07/Some-ZCE-Mock-Exam-Questions" target="_blank">Beispielfragen</a> habe ich in meinem Blog bereits gepostet.</p> <p style="font-weight: bold;">Vom Niveau her fand ich die eigentliche Pr&uuml;fung etwas schwieriger als die Probeexamen. Da diese aber nicht allzu teuer sind, kann ich jedem nur empfehlen, drei bis f&uuml;nf Tests zu kaufen. Mehr braucht's nicht! Ausserdem wiederholen sich die Fragen dann schon ...</p> <p>Etwa zwei Wochen besch&auml;ftigte ich mich intensiv (damit meine ich vielleicht zwei Stunden/Tag) mit der Pr&uuml;fungsvorbereitung. Danach viel ich irgendwie wieder in ein kleines Loch, worauf ich mich spontan in den fr&uuml;hen Morgenstunden (nach einem Samstagabend ...) f&uuml;r den Test anmeldete - f&uuml;r den kommenden Mittwoch. Die n&auml;chsten drei Tage lernte ich deshalb nochmals fleissig, machte noch einen Probeexamen und freute mich dann ganz entspannt auf die Pr&uuml;fung. :P</p> <h2>Meine Pr&uuml;fung</h2> <p>Besagten Mittwoch um 10:30 Uhr stand ich auf der Matte eines Pearson VUE Testcenters in Bern. Pearson VUE f&uuml;hrt f&uuml;r Zend die Examen in zertifizierten Testcentern durch. Dies hat den Vorteil, dass man sogar in jeder gr&ouml;sseren Schweizer Stadt die Zertifizierung machen kann. Sehr praktisch, da man sich Ort, Datum und Zeit ziemlich flexibel aussuchen kann.</p> <p>Nach einem Schluck Wasser und meiner Unterschrift unter dem Antrittsformular wurde ich auch schon in einen Raum voller Computer gef&uuml;hrt. Nebst mir waren nur etwa zwei weitere Personen anwesend, die aber (ziemlich sicher) eine andere Zeritifizierung machten. Ein Aufseher war nicht im Raum, jedoch wurde der Raum Kamera&uuml;berwacht. Ich fand die Atmosph&auml;re allerdings sehr entspannt und ich konnte mich gut konzentrieren.</p> <p>Was mir etwas Probleme bereitete, war, dass ich den Test auf Deutsch machte, obwohl ich mich ganzheitlich auf Englisch vorbereitete. Gewisse Fachbegriffe klangen einfach komisch und ich &uuml;bersetzte mir die Fragen des&ouml;fteren ins Englische, damit ich ein besseres Verst&auml;ndnis erlangte. Je nach Englischkenntnissen w&uuml;rde ich also empfehlen, den Test auf Englisch zu machen.<br />Ausserdem gab es eine Multiple Choice-Frage die laut Fragestellung drei Antworten erwartete, man aber nur zwei ausw&auml;hlen konnte. Die etwas &uuml;berforderte Angestellte des Testcenters konnte mir dabei auch nicht wirklich helfen (nach dem Motto: "Reboot tut immer gut").</p> <p>Die 90 Minuten waren - wie schon bei den Probeexamen - mehr als gut berechnet und so konnte ich ohne Probleme nochmals alle Fragen durchgehen und trotzdem fr&uuml;hzeitig beenden (etwa nach 70 - 75 Minuten). Die Schwierigkeit des Tests w&uuml;rde ich als "fortgeschritten" einstufen. Man muss sicher kein Profi sein, wer sich jedoch nicht tiefer mit der Sprache besch&auml;ftigt, wird kaum eine Chance haben.</p> <p>Und ja, erfreulicherweise bestand ich und seit dem 22. Juli darf ich mich offiziell "Zend Certified Engineer" nennen. :-)</p> <p>@See: <a class="DefaultLink" href="http://www.zend.com/zce.php?c=ZEND011434&amp;r=231232923" target="_blank">Mein ZCE Profil</a></p> <p>Fragen beantworte ich nat&uuml;rlich gerne in den Comments!</p> <h2>Gewinnspiel</h2> <p>Wie geschrieben habe ich noch f&uuml;nf offene Testexamen zu verschenken. Per Twitter (@phphil) m&ouml;chte ich deshalb gerne wissen, an welchem Wochentag ich mich f&uuml;r den Test angemeldet (nicht teilgenommen) habe. Sobald ein paar Teilnahmen eingegangen sind, werde ich einen Gewinner auslosen. Viel Gl&uuml;ck!</p> http://bigwhoop.ch/artikel/39/2009-12-08/Wie-ich-Zend-Certified-Engineer-wurde-mit-Gewinnspiel info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/39/2009-12-08/Wie-ich-Zend-Certified-Engineer-wurde-mit-Gewinnspiel Tue, 08 Dec 2009 18:01:25 +0100 Meine Lieblingsmomente aus Film und Serie Szenen die mir in Erinnerung blieben und ich immer wieder gerne schaue. Kommen bestimmt noch ein paar dazu. Später. <p><strong>Szenen die mir in Erinnerung blieben und ich immer wieder gerne schaue. Kommen bestimmt noch ein paar dazu. Später.</strong></p><p> <script src="/js/swfobject.js" type="text/javascript"></script> </p> <h2>Die Tanzszene aus NAPOLEON DYNAMITE</h2> <div id="player1">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/napoleon_dynamite_dance.flv&dock=false'); so.write('player1'); // --></script> </p> <h2>Die Tanzszene aus HOT ROD und der anschliessende Fall</h2> <div id="player2">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/hot_rod_dance_and_fall.flv&dock=false'); so.write('player2'); // --></script> </p> <h2>Eine weitere klitzekleine Tanzeinlage in HOT ROD</h2> <div id="player3">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/hot_rod_little_dance.flv&dock=false'); so.write('player3'); // --></script> </p> <h2>Jim Carries Andy Kaufman Interpretation in MAN ON THE MOON</h2> <div id="player4">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/man_on_the_moon_mighty_mouse.flv&dock=false'); so.write('player4'); // --></script> </p> <h2>Barneys Video R&eacute;sum&eacute; aus HOW I MET YOUR MOTHER</h2> <div id="player5">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/barneys_video_resume.flv&dock=false'); so.write('player5'); // --></script> </p> <h2>Die Verfolgungsjagd aus OBSERVE AND REPORT</h2> <div id="player6">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/observe_and_report_chase_scene.flv&dock=false'); so.write('player6'); // --></script> </p> <h2>Der Smalltalk in ZACK AND MIRI MAKE A PORNO</h2> <div id="player7">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/zack_and_miri.flv&dock=false'); so.write('player7'); // --></script> </p> <h2>Der Tod spielt Bass in BILL AND TED'S BOGUS JOURNEY</h2> <div id="player8">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/death_in_bill_and_ted.flv&dock=false'); so.write('player8'); // --></script> </p> <h2>Der Drill am Anfang von FULL METAL JACKET</h2> <div id="player9">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/full_metal_jacket_thrill.flv&dock=false'); so.write('player9'); // --></script> </p> <h2>Das Ende von ESCAPE FROM LA</h2> <div id="player10">Loading ...</div> <p> <script type="text/javascript"><!-- var so = new SWFObject('/swf/mediaplayer/player.swf','mpl','740','440','9'); so.addParam('allowscriptaccess','always'); so.addParam('allowfullscreen','true'); so.addParam('flashvars','&file=http://pub.bigwhoop.ch/fav-vids/escape_from_la_ending.flv&dock=false'); so.write('player10'); // --></script> </p> http://bigwhoop.ch/artikel/36/2009-06-08/Meine-Lieblingsmomente-aus-Film-und-Serie info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/36/2009-06-08/Meine-Lieblingsmomente-aus-Film-und-Serie Mon, 08 Jun 2009 18:03:35 +0200 FizzBuzz, Baby!!! ... etwas woran viele, viele Programmierer scheinbar scheitern. <p><strong>... etwas woran viele, viele Programmierer scheinbar scheitern.</strong></p><p>Das Thema ist zwar schon etwas &auml;lter, hat mich aber erst jetzt erreicht.</p> <p>Eine These besagt, dass Programmierer die einfache Probleme nicht l&ouml;sen k&ouml;nnen, auch ihre M&uuml;he mit komplexe(re)n Problemen haben - selbst wenn sie seit langem programmieren und als erfahren gelten. Dies soll sich vorallem durch lange Entwicklungszeit ausdr&uuml;cken.</p> <p>Da sich auf ausgeschriebene Stellen scheinbar viele Interessenten bewerben (keine Ahnung inwiefern man dies auf Europa und speziell aufs Webdevelopment &uuml;bertragen kann), hat <a class="DefaultLink" href="http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/" target="_blank">ein gewitzer, junger Herr namens Imran</a> ein Kinderspiel f&uuml;r die Softwareentwicklung adaptiert: Die sogenannten FizzBuzz Fragen.</p> <p>Dazu nennt er ein Beispiel, welches von einem Bewerber w&auml;hrend des Vorstellungsgespr&auml;ches gel&ouml;st werden soll:</p> <blockquote>Write a program that prints the numbers from 1 to 100. But for multiples of three print &ldquo;Fizz&rdquo; instead of the number and for the multiples of five print &ldquo;Buzz&rdquo;. For numbers which are multiples of both three and five print &ldquo;FizzBuzz&rdquo;.</blockquote> <p>Frei &uuml;bersetzt ...</p> <blockquote>Schreibe eine Anwendung, welche die Nummern 1 bis 100 ausgibt. Anstelle von Vielfachen von 3 soll aber das Wort "Fizz", anstelle von Vielfachen von 5 das Wort "Buzz" und anstelle von Vielfachen von 3 und 5 das Wort "FizzBuzz" ausgegeben werden.</blockquote> <p>Laut mehreren Posts in der Blogosph&auml;re scheinen an dieser doch relativ einfachen Aufgabe viele, viele Anw&auml;rter zu scheitern, bzw. mehr als 10 Minuten zu brauchen. Klingt aus meiner Sicht unglaublich ...</p> <p>Auf der 2. Seite gibt's meine L&ouml;sung. Nun viel Spass beim Knobbeln! ;-)</p><h2>Meine L&ouml;sung</h2> <pre name="code" class="php">foreach (range(1, 100) as $i) { switch (0) { case $i % 15 : echo 'FizzBuzz'; break; case $i % 3 : echo 'Fizz'; break; case $i % 5 : echo 'Buzz'; break; default : echo $i; break; } echo '&lt;br /&gt;'; }</pre> <p>Erzeugt folgende Ausgabe ...</p> <pre>1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 ...</pre> http://bigwhoop.ch/artikel/35/2009-07-29/FizzBuzz-Baby info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/35/2009-07-29/FizzBuzz-Baby Wed, 29 Jul 2009 11:00:52 +0200 Der Unterschied zwischen <em>valid</em> und <em>well-formed</em> Das W3C bietet einen tollen Dienst zum Validieren von (X)HTML Dokumenten. Doch was heisst eigentlich <em>valid</em>? Anhand von XHTML, bzw. XML möchte ich da etwas Klarheit schaffen. <p><strong>Das W3C bietet einen tollen Dienst zum Validieren von (X)HTML Dokumenten. Doch was heisst eigentlich <em>valid</em>? Anhand von XHTML, bzw. XML möchte ich da etwas Klarheit schaffen.</strong></p><p>Ein Beispiel erleichtert wie immer den Einstieg.</p> <pre name="code" class="xml">&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt; &lt;root /&gt;</pre> <p>Entgegen weitverbreiteter Annahme ist dieses XML Snippet nicht <em>valid</em>, sondern "nur" <em>well-formed</em> (wohlgeformt). Dies bedeutet, dass zwar die Regeln der XML Syntax eingehalten wurden und ein Parser problemlos mit dem Code umgehen k&ouml;nnte, aber die verwendete Struktur und deren Elemente nicht einer bestimmten Grammatik unterliegen. Man kann dies durchaus mit der Grammatik der deutschen Sprache vergleichen. In dieser ist zum Beispiel definiert, dass Nomen gross geschrieben werden. Ergo ist die Grammatik falsch, sobald ein Nomen klein geschrieben wird.</p> <p>Da XML eine Form der Darstellung ist (als Vergleich k&ouml;nnen die lateinischen Zeichen herhalten), enh&auml;lt sie per se keine grammatikalischen Regeln. Genauso wie ich mit den lateinischen Zeichen sowohl deutsche, also auch englische Texte schreiben kann. Will ich einen Satz auf deutsche Grammatik &uuml;berpr&uuml;fen, muss da irgendwie ein Bezug bestehen. Bei der Sprache ist dieser durch Metadaten (z.B. sagt mir jemand der folgende Text ist Deutsch) oder durch Erraten (wenn ich einen Text lese, erkenne ich grunds&auml;tzlich in welcher Sprache er geschrieben ist, solange ich die Sprache "kenne") gegeben.</p> <p>Bei XML muss dieser Bezug aber explizit hergestellt werden. Und dazu gibt es zwei M&ouml;glichkeiten:</p> <ul> <li>per Document Type Definition (DTD)</li> <li>per XML Schemas</li> </ul> <p>Da letztere M&ouml;glichkeit f&uuml;r unser Beispiel nicht von Relevanz ist, m&ouml;chte ich auch nicht n&auml;her darauf eingehen.</p> <h2>Document Type Definition</h2> <blockquote>Eine Dokumenttypdefinition (englisch Document Type Definition, DTD, auch Schema-Definition oder DOCTYPE) ist ein Satz an Regeln, der benutzt wird, um Dokumente eines bestimmten Typs zu deklarieren. [...] Die Dokumenttypdefinition besteht dabei aus Elementtypen, Attributen von Elementen, Entit&auml;ten und Notationen. Konkret hei&szlig;t das, dass in einer DTD die Reihenfolge, die Verschachtelung der Elemente und die Art des Inhalts von Attributen festgelegt wird - kurz gesagt: die Struktur des Dokuments.</blockquote> <p>Soviel zur Wikipedia-Definition. Auch hier sagt ein Beispiel wieder mehr als lange, kryptische S&auml;tze. Vergleichen wir die DTD f&uuml;r <a class="DefaultLink" href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" target="_blank">XHTML 1.0 Strict</a> und <a class="DefaultLink" href="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" target="_blank">XHTML 1.0 Transitional</a> bez&uuml;glich der erlaubten Attribute des <code>a</code>-Elements (Anchor).</p> <pre>&lt;!ATTLIST A id ID #IMPLIED class CDATA #IMPLIED style %StyleSheet; #IMPLIED title %Text; #IMPLIED lang %LanguageCode; #IMPLIED xml:lang %LanguageCode; #IMPLIED dir (ltr|rtl) #IMPLIED onclick %Script; #IMPLIED ondblclick %Script; #IMPLIED onmousedown %Script; #IMPLIED onmouseup %Script; #IMPLIED onmouseover %Script; #IMPLIED onmousemove %Script; #IMPLIED onmouseout %Script; #IMPLIED onkeypress %Script; #IMPLIED onkeydown %Script; #IMPLIED onkeyup %Script; #IMPLIED accesskey %Character; #IMPLIED tabindex %Number; #IMPLIED onfocus %Script; #IMPLIED onblur %Script; #IMPLIED charset %Charset; #IMPLIED type %ContentType; #IMPLIED name NMTOKEN #IMPLIED href %URI; #IMPLIED hreflang %LanguageCode; #IMPLIED rel %LinkTypes; #IMPLIED rev %LinkTypes; #IMPLIED shape %Shape; "rect" coords %Coords; #IMPLIED &gt; </pre> <p>Dies ist der Auszug aus der DTD von XHTML 1.0 Strict. Die Definition f&uuml;r XHTML 1.0 Transitional unterscheidet sich nur in einer zus&auml;tzlichen Zeile:</p> <pre>target %FrameTarget; #IMPLIED </pre> <p>Diese erlaubt, wie man sich denken kann, die Verwendung des <code>target</code>-Attributes in XHTML 1.0 Transitional.</p> <pre name="code" class="html">&lt;!-- Nicht valid in XHTML 1.0 Strict --&gt; &lt;!-- Valid in XHTML 1.0 Transitional --&gt; &lt;a href="http://example.org" target="_blank"&gt;Test&lt;/a&gt;</pre> <p>Zur Erinnerung: Der Code ist auch <em>well-formed</em>, allerdings hat dies nichts mit der DTD zu tun, sondern mit der XML Syntax.</p> <h2>Fazit</h2> <p>Da der Unterschied zwischen <em>well-formed</em> und <em>valid</em> jetzt klar ist, muss man sich nur selbst etwas an der Nase nehmen und im Kontext stehts den richtigen Ausdruck verwenden. Aus Erfahrung passiert der Fehler meist in Gespr&auml;chen und aus der Tatsache, dass f&uuml;r eigene XML Strukturen keine DTD geschrieben werden.</p> http://bigwhoop.ch/artikel/34/2009-07-27/Der-Unterschied-zwischen-emvalidem-und-emwell-formedem info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/34/2009-07-27/Der-Unterschied-zwischen-emvalidem-und-emwell-formedem Mon, 27 Jul 2009 11:39:35 +0200 Namenskonvention von Interfaces und abstrakten Klassen in PHP 5.3 Durch die Verwendung von Namespaces traf ich auf ein Problem hinsichtlich der Benennung meiner Interfaces und abstrakten Klassen. <p><strong>Durch die Verwendung von Namespaces traf ich auf ein Problem hinsichtlich der Benennung meiner Interfaces und abstrakten Klassen.</strong></p><p>Als &uuml;berzeugter Zend Framework-Nutzer folge ich beim Programmieren auch dessen Coding Guidelines. Dies bedeutet f&uuml;r Interfaces und abstrakte Klassen folgende Konvention:</p> <pre name="code" class="php">// Interface in Zend/View/Interface.php interface Zend_View_Interface {} // Abstrakte Klasse in Zend/View/Abstract.php abstract class Zend_View_Abstract {}</pre> <p>Diese Konvention hat den Vorteil, dass man durch das Ersetzen des Unterstrichs durch den Verzeichnisseparator auf einfache Art auf den Speicherort der Klasse/des Interfaces schliessen kann.</p> <p>Da wir aber mittlerweile alle wissen, dass in PHP 5.3 Namespaces eingef&uuml;hrt wurden, &auml;ndert sich diese Konventionen grundlegend.</p> <pre name="code" class="php">// Interface in Zend/View/Interface.php namespace Zend\View; interface Interface {} // Abstrakte Klasse in Zend/View/Abstract.php namespace Zend\View; abstract class Abstract {}</pre> <p>Wie ihr bestimmt bemerkt hab ist obiges Beispiel unbrauchbar. Da <code>interface</code> und <code>abstract</code> reservierte W&ouml;rter sind, k&ouml;nnen wir sie nicht f&uuml;r Deklarationen verwenden.</p> <p>Als L&ouml;sungansatz schweben mir da mehrere Varianten vor.</p> <h2>"Hungarische Notation"</h2> <p><code>I</code> f&uuml;r Interface und <code>A</code> f&uuml;r abstrakte Klassen.</p> <pre name="code" class="php">// Interface in Zend/View/IView.php namespace Zend\View; interface IView {} // Abstrakte Klasse in Zend/View/AView.php namespace Zend\View; abstract class AView {}</pre> <p>... oder ohne das Package ...</p> <pre name="code" class="php">// Interface in Zend/IView.php namespace Zend; interface IView {} // Abstrakte Klasse in Zend/AView.php namespace Zend; abstract class AView {}</pre> <h2>Als Teil des Subpackages</h2> <pre name="code" class="php">// Interface in Zend/ViewInterface.php namespace Zend; interface ViewInterface {} // Abstrakte Klasse in Zend/ViewAbstract.php namespace Zend; abstract class ViewAbstract {}</pre> <p>... oder in umgekehrter Schreibweise ...</p> <pre name="code" class="php">// Interface in Zend/InterfaceView.php namespace Zend; interface InterfaceView {} // Abstrakte Klasse in Zend/AbstractView.php namespace Zend; abstract class AbstractView {}</pre> <h2>Beschreibende Interface-Namen</h2> <p>Wie in der SPL: <code>Countable</code>, <code>Traversable</code>, etc.</p> <pre name="code" class="php">// Interface in Zend/View/Viewable.php namespace Zend\View; interface Viewable {}</pre> <p>Jetzt seid ihr dran: Welche Idee bevorzugt ihr? Habt ihr gar einen anderen Vorschlag?</p> http://bigwhoop.ch/artikel/33/2009-07-19/Namenskonvention-von-Interfaces-und-abstrakten-Klassen-in-PHP-53 info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/33/2009-07-19/Namenskonvention-von-Interfaces-und-abstrakten-Klassen-in-PHP-53 Sun, 19 Jul 2009 13:53:32 +0200 Mathematik revisited: Umrechnen von Zahlensystemen Momentan bin ich dabei gewisse schulische Grundlagen wieder etwas aufzufrischen. Dazu gehört auch das Umrechnen von Zahlensystemen im Kopf. Hier ein kleiner Spickzettel. <p><strong>Momentan bin ich dabei gewisse schulische Grundlagen wieder etwas aufzufrischen. Dazu gehört auch das Umrechnen von Zahlensystemen im Kopf. Hier ein kleiner Spickzettel.</strong></p><h2>Hexadezimal <code>0xE6FA</code> nach Oktal</h2> <p>Zur erfolgreichen Umrechnung muss das Hexadezimalsystem bekannt sein. D.h. man muss wissen, dass A = 10, B = 11, ... F = 15 ist. Zur Umrechnung ins oktale Zahlensystem gehen wir den Umweg &uuml;ber das Dezimalsystem.</p> <h3>1. Hexadezimal nach Dezimal (= Basis 16)<br /></h3> <pre>E/14 * 16 * 16 * 16 = 57344 6 * 16 * 16 = 1536 F/15 * 16 = 240 A/10 = 10 ------------------------------- = 59130 </pre> <p>Die Basis ist austauschbar. Wenn man vom Oktal- ins Dezimalsystem rechnen m&ouml;chte, m&uuml;sste man einfach mit 8 multiplizieren.</p> <h3>2. Dezimal nach Oktal (= Basis 8)<br /></h3> <pre>59130 / 8 = 7391 Rest 2 7391 / 8 = 923 Rest 7 923 / 8 = 115 Rest 3 115 / 8 = 14 Rest 3 14 / 8 = 1 Rest 6 1 / 8 = 0 Rest 1 ------------------------- -&gt; 0163372 </pre> <p>Das Result ergibt sich hier aus den zusammengefassten Restzahlen. Auch hier kann man die Basis einfach austauschen. M&ouml;chte man vom Dezimal- ins Hexadezimalsystem umrechnen, w&uuml;rde man durch 16 teilen (und nat&uuml;rlich Rest = 13 noch in Rest = D umwandeln).</p> http://bigwhoop.ch/artikel/32/2009-07-16/Mathematik-revisited-Umrechnen-von-Zahlensystemen info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/32/2009-07-16/Mathematik-revisited-Umrechnen-von-Zahlensystemen Thu, 16 Jul 2009 02:42:30 +0200 Zend Extensions in PHP 5.3 laden Ein kleiner, aber wichtiger Change in PHP 5.3, der mich ein paar Stunden kostete ... <p><strong>Ein kleiner, aber wichtiger Change in PHP 5.3, der mich ein paar Stunden kostete ...</strong></p><p>Gestern r&auml;umte ich meine lokale Entwicklungsumgebung auf. XAMPP flog raus, Apache 2.2 und PHP 5.3 kamen "standalone" rein (MySQL l&auml;uft bei mir auf einem Heimserver). Mir war das ganze Gewurstel einfach zu un&uuml;bersichtlich geworden.</p> <p>Jedenfalls kam ich im Zuge dieser Neuinstallationen-/konfigurationen auch an den Punkt, wo ich mein geliebtes Xdebug installieren wollte. Aus irgendeinem Grund wollte sich dieses jedoch nicht als Zend Extension laden lassen. Eine Fehlermeldung erhielt ich nicht und als normale Extension klappte es wunderbar.</p> <p>Heute konnte mir der Twitter-Channel von Xdebug die einfache L&ouml;sung mitteilen: <strong>Anstatt <code>zend_extension_ts</code> muss in PHP 5.3 nur noch <code>zend_extension</code> verwendet werden. </strong>Die Direktiven <code>zend_extension_ts</code> und <code> </code><code>zend_extension_debug</code> werden seit PHP 5.3 ignoriert.</p> <p>Leider findet sich zu diesem Change weder im <a class="DefaultLink" href="http://ch.php.net/manual/en/ini.core.php#ini.zend-extension-ts" target="_blank">PHP Manual</a>, noch im <a class="DefaultLink" href="http://xdebug.org/docs/install" target="_blank">Xdebug Installation Guide</a> ein Hinweis. Ich hoffe, dies &auml;ndert sich noch ... :-)</p> <p>Den einzigen Hinweis fand ich im <a class="DefaultLink" href="http://ch.php.net/manual/en/migration53.ini.php" target="_blank">Migration Guide f&uuml;r PHP 5.3</a>: <em>"zend_extension_debug and zend_extension_ts have been removed. Use the zend_extension directive to load all Zend Extensions."</em></p> <h2>Nachtrag</h2> <p>Derick hat soeben die Xdebug Dokumentation geupdatet. Wunderbar. :-)</p> http://bigwhoop.ch/artikel/31/2009-12-07/Zend-Extensions-in-PHP-53-laden info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/31/2009-12-07/Zend-Extensions-in-PHP-53-laden Mon, 07 Dec 2009 10:47:37 +0100 PHP Arrays - Eine All-In-One Lösung Wer ausschliesslich mit PHP programmiert hat eine etwas eigene Sicht auf Arrays. In diesem Artikel möchte ich da ein wenig Aufklärung leisten. <p><strong>Wer ausschliesslich mit PHP programmiert hat eine etwas eigene Sicht auf Arrays. In diesem Artikel möchte ich da ein wenig Aufklärung leisten.</strong></p><p>Das PHP Array ist ein enorm m&auml;chtiges Konstrukt. Es ist - wie PHP auch - sehr flexibel gebaut und auf viele, unterschiedliche Arten verwendbar. Im Folgenden setze ich das Grundwissen voraus, wie Arrays in PHP angewandt werden. Sicherheitshalber noch einmal ein paar Fakten:</p> <ul> <li>Indexe (Keys) k&ouml;nnen vom Typ Integer oder String sein. Floats werden zu einem Integer gecastet</li> <li>Arrays oder Objekte k&ouml;nnen nicht als Index verwendet werden</li> </ul> <pre name="code" class="php">// Array mit numerischen Indexen $a = array('Eins', 'Zwei', 'Drei'); // Assoziatives Array $a = array('Null' =&gt; 'Eins', 'Eins' =&gt; 'Zwei', 'Zwei' =&gt; 'Drei'); // Mixed Array $a = array(4 =&gt; 'Eins', 'F&uuml;nf' =&gt; 'Zwei', 'Drei');</pre> <p>Der interne Zeiger wird bei jedem numerischen Key um eins hochgez&auml;hlt. Im letztem Beispiel hat das Element <code>Drei</code> deshalb den Index <code>5</code>.</p> <p>In den meisten Programmiersprachen gibt es mehrere Konstrukte zur Haltung von Daten. Dies hat vor allem den Vorteil, dass die Daten klarer strukturiert und je nach Anwendung auf definierte Art und Weise gehandhabt werden. Im Folgenden m&ouml;chte ich auf ein paar dieser Konstrukte eingehen, sie auf einfache Art erkl&auml;ren und anschliessend zeigen, wie sie mittels SPL auch in PHP verwendet werden k&ouml;nnen.</p> <h2>Hashtable</h2> <p>Eine Hashtable, oder auch Hashmap, kann man sich als klassisches, assoziatives PHP Array vorstellen. Allerdings ohne besagte Limitierungen hinsichtlich Indexe. Die Definition ist ein bisschen w&auml;sserig, da es in PHP keine strenge Typisierung gibt. In vielen anderen Programmiersprachen ist ein Array immer von nur einem Typ (String-Array, Byte-Array, etc.).</p> <pre name="code" class="php">class Hashtable implements ArrayAccess { protected $_data = array(); public function offsetSet($key, $value) { $key = $this-&gt;_normalizeKey($key); $this-&gt;_data[$key] = $value; } public function offsetGet($key) { $key = $this-&gt;_normalizeKey($key); return $this-&gt;_data[$key]; } public function offsetUnset($key) { $key = $this-&gt;_normalizeKey($key); unset($this-&gt;_data[$key]); } public function offsetExists($key) { $key = $this-&gt;_normalizeKey($key); return isset($this-&gt;_data[$key]); } &nbsp; protected function _normalizeKey($key) { if ($key instanceof stdClass) { $key = spl_object_hash($key); } elseif (is_array($key)) { $key = md5(serialize($key)); } return $key; } } $h = new Hashtable(); $o1 = new stdClass(); $o2 = new stdClass(); $h[$o1] = $o2;</pre> <p>In der sogenannten Standard PHP Library (SPL) gibt es eine Klasse zum Speichern von Objekten. Da diese fest in PHP integriert ist, hat sie klare Geschwindigkeitsvorteile gegen&uuml;ber einer eigenen L&ouml;sung in PHP. Etienne Kneuss hat dazu in <a class="DefaultLink" href="http://www.colder.ch/news/01-08-2009/34/splobjectstorage-for-a-fa.html" target="_blank">seinem Blog</a> weitere, interessante Informationen.</p> <pre name="code" class="php">$s = new SplObjectStorage(); $o1 = new stdClass(); $o2 = new stdClass(); // Seit PHP 5.1 $s-&gt;attach($o1); $s-&gt;detach($o1); // Seit PHP 5.3 $s[$o1] = $o2;</pre> <h2>Queue</h2> <p>Eine Queue iteriert im sogenannten FIFO-Modus (First In, First Out) &uuml;ber die Elemente. Dies bedeutet, dass die Elemente zuerst zur&uuml;ckgegeben werden, die auch zuerst zuerst hinzugef&uuml;gt wurden. Dies entspring dem Standard-Iterierungsverfahren von Arrays in PHP (z.B. bei <code>foreach()</code>).</p> <pre name="code" class="php">class Queue { protected $_data = array(); public function enqueue($value) { $this-&gt;_data[] = $value; return $this; } public function dequeue() { return array_shift($this-&gt;_data); } } $q = new Queue(); $q-&gt;enqueue('Eins') -&gt;enqueue('Zwei') -&gt;enqueue('Drei'); echo $q-&gt;dequeue(); // Eins echo $q-&gt;dequeue(); // Zwei echo $q-&gt;dequeue(); // Drei</pre> <p>Auch hier kann die SPL <strong>seit PHP 5.3</strong> helfen:</p> <pre name="code" class="php">$q = new SplQueue(); $q[] = 1; $q[] = 2; $q[] = 3; // 1, 2, 3 foreach ($q as $e) { echo $e; }</pre> <h2>Stack</h2> <p>Der Stack ist sowas wie das Gegenst&uuml;ck zu einer Queue. Er verwendet das LIFO-Verfahren (Last In, First Out), welches die Element zuerst zur&uuml;ckgibt, die zuletzt angeh&auml;ngt wurden.</p> <pre name="code" class="php">class Stack { protected $_data = array(); public function push($value) { $this-&gt;_data[] = $value; return $this; } public function pop() { return array_pop($this-&gt;_data); } } $s = new Stack(); $s-&gt;push('Eins') -&gt;push('Zwei') -&gt;push('Drei'); echo $s-&gt;pop(); // Drei echo $s-&gt;pop(); // Zwei echo $s-&gt;pop(); // Eins</pre> <p>Und wieder kann uns die SPL helfen. Wiederum ist <strong>PHP 5.3</strong> Kriterium.</p> <pre name="code" class="php">$q = new SplStack(); $q[] = 1; $q[] = 2; $q[] = 3; // 3, 2, 1 foreach ($q as $e) { echo $e; }</pre> <h2>Dictionary</h2> <p>Den Dictionary kann man sich als assoziatives Array mit fest definierten Typen f&uuml;r Key und Value vorstellen. Hier eine sehr abstrakte Implementierung.</p> <pre name="code" class="php">class Dictionary { protected $_keyType = null; protected $_valueType = null; protected $_data = array(); public function __construct($keyType, $valueType) { $this-&gt;_keyType = $keyType; $this-&gt;_valueType = $valueType; } public function add($key, $value) { if (!$this-&gt;_assert($this-&gt;_keyType, $key)) { throw new Exception('Key must be of type "' . $this-&gt;_keyType . '"'); } if (!$this-&gt;_assert($this-&gt;_valueType, $value)) { throw new Exception('Value must be of type "' . $this-&gt;_valueType . '"'); } // Adding key/value pair // ... } protected function _assert($type, $value) { if (function_exists('is_' . $type)) { return call_user_func('is_' . $type, $value); } return $value instanceof $type; } } $d = new Dictionary('int', 'stdClass'); $d-&gt;add(1, new stdClass()); // Success $d-&gt;add('1', new stdClass()); // Fail $d-&gt;add(1, 'foobar'); // Fail</pre> <p>Hierzu gibt es leider keine Klasse in der SPL.</p> <h2>Weitere Datenstrukturen in der SPL</h2> <p>Die SPL kennt noch weitere Konstrukte zur Datenhaltung, wie SplHeap, SplPriorityQueue, etc. Hier m&ouml;chte ich aber nur noch auf eine bestimmte Struktur eingehen: <strong>SplFixedArray</strong>.</p> <p>Das SplFixedArray gibt es ebenfalls erst seit PHP 5.3 und unterscheidet sich in folgenden Punkten vom klassischen PHP Array:</p> <ol> <li>Das Array hat eine feste Gr&ouml;sse, wird also nicht dynamisch erweitert</li> <li>Das Array kann nur numerische Indexe haben</li> <li>Das SplFixedArray ist eine viel schnellere und schlankere Implementierung als herk&ouml;mmliche Arrays</li> </ol> <pre name="code" class="php">$a = new SplFixedArray(2); $a[0] = 'Eins'; $a[1] = 'Zwei'; // Triggert eine RuntimeException, da die Gr&ouml;sse des Arrays &uuml;berschritten wurde $a[2] = 'Drei'; // Folgendes geht aber $a-&gt;setSize(3); $a[2] = 'Drei';</pre> <p>Ich empfehle als Lekt&uuml;re die <a class="DefaultLink" href="http://ch2.php.net/spl" target="_blank">PHP Dokumentation zur SPL</a>. Ausserdem findet ihr im Entwicklerblog von studiVZ eine <a class="DefaultLink" href="http://developer.studivz.net/2009/03/18/php-spl-data-structures-benchmark/" target="_blank">interessante Benchmark betreffend SplQueue und SplStack</a>, und im Blog von IDONTPLAYDARTS eine <a class="DefaultLink" href="http://www.idontplaydarts.com/2009/06/benchmarking-splfixedarray-access-speed/">Benchmark zu SplFixedArray</a>.</p> <p>Haut rein, in die Tasten! :)</p> http://bigwhoop.ch/artikel/29/2009-09-07/PHP-Arrays---Eine-All-In-One-Loesung info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/29/2009-09-07/PHP-Arrays---Eine-All-In-One-Loesung Mon, 07 Sep 2009 07:16:17 +0200 Some ZCE Mock Exam Questions Some questions from the Zend Certified Engineer (ZCE) Mock Exams <p><strong>Some questions from the Zend Certified Engineer (ZCE) Mock Exams</strong></p><p>You'll find my (!) answers on the next page. Have fun!</p> <h3>Question 1</h3> <p>What are the primary benefits of object oriented programming?</p> <p>Answers: (choose 3)</p> <ul> <li>Maintainability</li> <li>Execution Speed</li> <li>Encapsulation</li> <li>Code Reuse</li> </ul> <hr /> <h3>Question 2</h3> <p>The <code>_____</code> keyword is used to block any overriding of a class/method by a subclass.</p> <p>Answers:</p> <ul> <li>static</li> <li>None of the above</li> <li>protected</li> <li>final</li> <li>private</li> </ul> <hr /> <h3>Question 3</h3> <p>Event-based XML parsing is an example of which parsing model?</p> <p>Answers:</p> <ul> <li>SAX</li> <li>DOM</li> <li>XML Object Mapping</li> <li>XPath</li> <li>XQuery</li> </ul> <hr /> <h3>Question 4</h3> <p>Which functions would be needed to translate the following string:</p> <pre>I love PHP 5</pre> <p>to the following?</p> <pre>5 PHP EVOL I </pre> <p>Answers: (choose 2)</p> <ul> <li>mirror()</li> <li>strtoupper()</li> <li>toupper()</li> <li>str_reverse()</li> <li>strrev()</li> </ul> <hr /> <h3>Question 5</h3> <p>Which two internal PHP interfaces provide functionality which allow you to treat an object like an array?</p> <p>Answers: (choose 2)</p> <ul> <li>iteration</li> <li>arrayaccess</li> <li>objectarray</li> <li>iterator</li> <li>array</li> </ul> <hr /> <h3>Question 6</h3> <p>Consider the following code snippet:</p> <pre name="code" class="php">$query = "INSERT INTO mytable (myinteger, mydouble, myblob, myvarchar) VALUES (?, ?, ?, ?)"; $statement = mysqli_prepare($link, $query); if(!$statement) { die(mysqli_error($link)); } /* The variables being bound to by MySQLi don't need to exist prior to binding */ mysqli_bind_param($statement, "idbs", $myinteger, $mydouble, $myblob, $myvarchar); /* ???????????? */ /* execute the query, using the variables as defined. */ if(!mysqli_execute($statement)) { die(mysqli_error($link)); }</pre> <p>Assuming this snippet is a smaller part of a correctly written script, what actions must occur in place of the ????? in the above code snippet to insert a row with the following values: 10, 20.2, foo, string ?</p> <p>Answer...</p> <ul> <li> A transaction must be begun and the variables must be assigned</li> <li> Each value must be assigned prior to calling mysqli_bind_param(), and thus nothing should be done</li> <li> Use mysqli_bind_value() to assign each of the values</li> <li> Assign $myinteger, $mydouble, $myblob, $myvarchar the proper values </li> </ul> <hr /> <h3>Question 7</h3> <p>Given the string:</p> <pre name="code" class="php">$var = "john@php.net";</pre> <p>Which of the following will extract the TLD (top level domain) of ".net" from the string?</p> <p>Answer...</p> <ul> <li>strstr($var, strpos($var, "."));</li> <li>substr($var, strpos($var, "@"));</li> <li>substr($var, strstr($var, "."));</li> <li>substr($var, strpos($var, ".") + 1);</li> <li>substr($var, strpos($var, ".")); </li> </ul> <hr /> <h3>Question 8</h3> <p>The ____ construct is particularly useful to assign your own variable names to values within an array.</p> <p>Answer...</p> <ul> <li>array_get_variables</li> <li>current</li> <li>each</li> <li>import_variables</li> <li>list </li> </ul> <hr /> <h3>Question 9</h3> <p>Given the following XML document in a SimpleXML object:</p> <pre name="code" class="xml">&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt; &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt; &lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"&gt; &lt;head&gt; &lt;title&gt;XML Example&lt;/title&gt; &lt;/head&gt; &lt;body&gt; &lt;p&gt; Moved to &amp;lt;&lt;a href="http://example.org/"&gt;http://www.example.org/&lt;/a&gt;.&amp;gt; &lt;br/&gt; &lt;/p&gt; &lt;/body&gt; &lt;/html&gt;</pre> <p>Select the proper statement below which will display the HREF attribute of the anchor tag.</p> <p>Answer...</p> <ul> <li>$sxe-&gt;body-&gt;p[0]-&gt;a[1]['href']</li> <li>$sxe-&gt;body-&gt;p-&gt;a-&gt;href</li> <li>$sxe-&gt;body-&gt;p-&gt;a['href']</li> <li>$sxe['body']['p'][0]['a']['href']</li> <li>$sxe-&gt;body-&gt;p[1]-&gt;a['href']</li> </ul> <hr /> <h3>Question 10</h3> <p>Consider the following script:</p> <pre name="code" class="php">$dom = new DOMDOcument(); $dom-&gt;load("myxmlfile.xml"); foreach($dom-&gt;documentElement-&gt;childNodes as $child) { if(($child-&gt;nodeType == XML_ELEMENT_NODE) &amp;&amp; $child-&gt;nodeName == "item") { foreach($child-&gt;childNodes as $item) { if(($item-&gt;nodeType == XML_ELEMENT_NODE) &amp;&amp; ($item-&gt;nodeName == "title")) { print "$item-&gt;firstChild-&gt;data\n"; } } } }</pre> <p>Assuming the referenced XML document exists and matches the parsing logic, what should be displayed when this script is executed?</p> <p>Answer...</p> <ul> <li>None of the above</li> <li>The XML of each 'title' node</li> <li>The XML of each 'item' node</li> <li>"Title" for every title node in the document</li> <li>The contents of every 'title' node which exists under an 'item' node </li> </ul> <hr /> <h3>Question 11</h3> <p>Which of the following is the best way to split a string on the "-=-" pattern?</p> <p>Answer...</p> <ul> <li>They all are equally proper methods</li> <li>str_split($string, strpos($string, "-=-"))</li> <li>preg_split("-=-", $string);</li> <li>explode("-=-" $string); </li> </ul> <hr /> <h3>Question 12</h3> <p>SimpleXML objects can be created from what types of data sources?</p> <p>Answers: (choose 3)</p> <ul> <li>A String</li> <li>An array</li> <li>A DomDocument object</li> <li>A URI</li> <li>A Database resource </li> </ul> <hr /> <h3>Question 13</h3> <p>Which of the following are valid PHP variables?</p> <p>Answers: (choose 4)</p> <ul> <li>@$foo</li> <li>&amp;$variable</li> <li>${0x0}</li> <li>$variable</li> <li>$0x0 </li> </ul> <hr /> <h3>Question 14</h3> <p>When implementing a permissions system for your Web site, what should always be done with regards to the session?</p> <p>Answer...</p> <ul> <li>None of the above</li> <li>You should not implement permission systems using sessions</li> <li>Sessions should be cleared of all data and re-populated</li> <li>The session key should be regenerated</li> <li>The session should be destroyed </li> </ul> <hr /> <h3>Question 15</h3> <p>SQL Injections can be best prevented using which of the following database technologies?</p> <p>Answers: (choose 1)</p> <ul> <li>All of the above</li> <li>Prepared Statements</li> <li>Persistent Connections</li> <li>Unbuffered Queries</li> <li>Query escaping </li> </ul> <hr /> <h3>Question 16</h3> <p>When attempting to prevent a cross-site scripting attack, which of the following is most important?</p> <p>Answer...</p> <ul> <li>Not writing Javascript on the fly using PHP</li> <li>Filtering Output used in form data</li> <li>Filtering Output used in database transactions</li> <li>Writing careful Javascript</li> <li>Filtering all input </li> </ul> <hr /> <h3>Question 17</h3> <p>What three special methods can be used to perform special logic in the event a particular accessed method or member variable is not found?</p> <p>Answers: (choose 3)</p> <ul> <li>__get($variable)</li> <li>__call($method, $params)</li> <li>__get($method)</li> <li>__set($variable, $value)</li> <li>__call($method) </li> </ul> <hr /> <h3>Question 18</h3> <p>When running PHP in a shared host environment, what is the major security concern when it comes to session data?</p> <p>Answer...</p> <ul> <li>Sessions on shared hosts are easily hijacked by outside malicious users</li> <li>All of the above</li> <li>You cannot use a custom data store in shared hosts</li> <li>Session data stored in the file system can be read by other scripts on the same shared host</li> <li>Users outside the shared host can access any site which created a session for them </li> </ul> <hr /> <h3>Question 19</h3> <p>A fingerprint of a string can be determined using which of the following?</p> <p>Answer...</p> <ul> <li>md5()</li> <li>hash()</li> <li>fingerprint()</li> <li>None of the above </li> </ul> <hr /> <h3>Question 20</h3> <p>When embedding PHP into XML documents, what must you ensure is true in order for things to function properly?</p> <p>Answer...</p> <ul> <li>Disabling of the short_tags PHP.ini directive</li> <li>Enabling the asp_tags PHP.ini directive</li> <li>That you have XPath support enabled in PHP 5</li> <li>That your XML documents are well-formed</li> <li>None of the above, PHP can be embedded in XML in all cases. </li> </ul> <hr /> <h3>Question 21</h3> <p>What is the output of the following code?</p> <pre name="code" class="php">$string = "111221"; for($i = 0; $i &lt; strlen($string); $i++) { $current = $string[$i]; $count = 1; while(isset($string[$i + $count]) &amp;&amp; ($string[$i + $count] == $current)) $count++; $newstring .= "$count{$current}"; $i += $count-1; } print $newstring;</pre> <p>Answer...</p> <ul> <li>312211</li> <li>3312212</li> <li>11221221</li> <li>221131</li> <li>3211122 </li> </ul> <hr /> <h3>Question 22</h3> <p>When working with a database, which of the following can be used to mitigate the possibility of exposing your database credientials to a malicious user?</p> <p>Answers: (choose 3)</p> <ul> <li>Moving all database credentials into a single file</li> <li>Moving all database credentials outside of the document root</li> <li>Restricting access to files not designed to be executed independently</li> <li>Setting creditial information as system environment variables</li> <li>Using PHP constants instead of variables to store credentials </li> </ul> <hr /> <h3>Question 23</h3> <p>Consider the following code:</p> <pre name="code" class="php">session_start(); if(!empty($_REQUEST['id']) &amp;&amp; !empty($_REQUEST['quantity'])) { $id = scrub_id($_REQUEST['id']); $quantity = scrub_quantity($_REQUEST['quantity']) $_SESSION['cart'][] = array('id' =&gt; $id, 'quantity' =&gt; $quantity) } /* .... */</pre> <p>What potential security hole would this code snippet produce?</p> <p>Answer...</p> <ul> <li>Cross-Site Scripting Attack</li> <li>There is no security hole in this code</li> <li>Code Injection</li> <li>SQL Injection</li> <li>Cross-Site Request Forgery </li> </ul> <hr /> <h3>Question 24</h3> <p>Which statement will return the third parameter passed to a function?</p> <p>Answer...</p> <ul> <li>$argv[3];</li> <li>$argv[2];</li> <li>func_get_args(3);</li> <li>func_get_arg(2);</li> <li>func_get_arg(3); </li> </ul> <hr /> <h3>Question 25</h3> <p>When is it important to validate data coming from an HTML form?</p> <p>Answer...</p> <ul> <li>Only when the fields are required</li> <li>Only when accepting file uploads</li> <li>Everywhere, except cookies</li> <li>Only when accepting forms using an input type of text or a &lt;textarea&gt; field</li> <li>None of the above </li> </ul> <hr /> <h3>Question 26</h3> <p>Which of the following extensions are no longer part of PHP 5 and have been moved to PECL?</p> <p>Answers: (choose 2)</p> <ul> <li>tidy</li> <li>mysql</li> <li>w32api</li> <li>curl</li> <li>dio</li> </ul> <hr /> <h3>Question 27</h3> <p>The following is a common XML structure used in service oriented architectures, what does it represent?</p> <pre name="code" class="php">&lt;?xml version="1.0"?&gt; &lt;methodCall&gt; &lt;methodName&gt;myMethod&lt;/methodName&gt; &lt;params&gt; &lt;param&gt; &lt;value&gt;&lt;string&gt;HI!&lt;/string&gt;&lt;/value&gt; &lt;/param&gt; &lt;/params&gt; &lt;/methodCall&gt;</pre> <p>Answer...</p> <ul> <li>None of the above</li> <li>A fragment of a complete SOAP request</li> <li>XML-RPC</li> <li>REST</li> <li>SOAP</li> </ul> <hr /> <h3>Question 28</h3> <p>Which of the following functions could be used to break a string into an array?</p> <p>Answers: (choose 3)</p> <ul> <li>array_split()</li> <li>split()</li> <li>string_split()</li> <li>preg_match_all()</li> <li>explode() </li> </ul> <hr /> <h3>Question 29</h3> <p>Which PCRE regular expression will match the string <code>PhP5-rocks?</code></p> <p>Answer...</p> <ul> <li>/^[hp1-5]*\-.*/i</li> <li>/[hp1-5]*\-.?/</li> <li>/[hp][1-5]*\-.*/</li> <li>/[PhP]{3}[1-5]{2,3}\-.*$/</li> <li>/[a-z1-5\-]*/ </li> </ul><p>I struck the wrong answers, according to my knowledge. Please drop me some lines if you find a mistake. Thx! :-)</p> <h3>Question 1</h3> <ul> <li>Maintainability</li> <li><span style="text-decoration: line-through;">Execution Speed</span></li> <li>Encapsulation</li> <li>Code Reuse</li> </ul> <hr /> <h3>Question 2</h3> <ul> <li><span style="text-decoration: line-through;">static</span></li> <li><span style="text-decoration: line-through;">None of the above</span></li> <li><span style="text-decoration: line-through;">protected</span></li> <li>final</li> <li><span style="text-decoration: line-through;">private</span></li> </ul> <hr /> <h3>Question 3</h3> <ul> <li>SAX</li> <li><span style="text-decoration: line-through;">DOM</span></li> <li><span style="text-decoration: line-through;">XML Object Mapping</span></li> <li><span style="text-decoration: line-through;">XPath</span></li> <li><span style="text-decoration: line-through;">XQuery</span></li> </ul> <hr /> <h3>Question 4</h3> <ul> <li><span style="text-decoration: line-through;">mirror()</span></li> <li>strtoupper()</li> <li><span style="text-decoration: line-through;">toupper()</span></li> <li><span style="text-decoration: line-through;">str_reverse()</span></li> <li>strrev()</li> </ul> <hr /> <h3>Question 5</h3> <ul> <li><span style="text-decoration: line-through;">iteration</span></li> <li>arrayaccess</li> <li><span style="text-decoration: line-through;">objectarray</span></li> <li>iterator</li> <li><span style="text-decoration: line-through;">array</span></li> </ul> <hr /> <h3>Question 6</h3> <ul> <li><span style="text-decoration: line-through;"> A transaction must be begun and the variables must be assigned</span></li> <li><span style="text-decoration: line-through;"> Each value must be assigned prior to calling mysqli_bind_param(), and thus nothing should be done</span></li> <li><span style="text-decoration: line-through;"> Use mysqli_bind_value() to assign each of the values</span></li> <li> Assign $myinteger, $mydouble, $myblob, $myvarchar the proper values </li> </ul> <hr /> <h3>Question 7</h3> <ul> <li><span style="text-decoration: line-through;">strstr($var, strpos($var, "."));</span></li> <li><span style="text-decoration: line-through;">substr($var, strpos($var, "@"));</span></li> <li><span style="text-decoration: line-through;">substr($var, strstr($var, "."));</span></li> <li><span style="text-decoration: line-through;">substr($var, strpos($var, ".") + 1);</span></li> <li>substr($var, strpos($var, ".")); </li> </ul> <hr /> <h3>Question 8</h3> <ul> <li><span style="text-decoration: line-through;">array_get_variables</span></li> <li><span style="text-decoration: line-through;">current</span></li> <li><span style="text-decoration: line-through;">each</span></li> <li><span style="text-decoration: line-through;">import_variables</span></li> <li>list </li> </ul> <hr /> <h3>Question 9</h3> <ul> <li><span style="text-decoration: line-through;">$sxe-&gt;body-&gt;p[0]-&gt;a[1]['href']</span></li> <li><span style="text-decoration: line-through;">$sxe-&gt;body-&gt;p-&gt;a-&gt;href</span></li> <li>$sxe-&gt;body-&gt;p-&gt;a['href']</li> <li><span style="text-decoration: line-through;">$sxe['body']['p'][0]['a']['href']</span></li> <li><span style="text-decoration: line-through;">$sxe-&gt;body-&gt;p[1]-&gt;a['href']</span></li> </ul> <hr /> <h3>Question 10</h3> <ul> <li><span style="text-decoration: line-through;">None of the above</span></li> <li><span style="text-decoration: line-through;">The XML of each 'title' node</span></li> <li><span style="text-decoration: line-through;">The XML of each 'item' node</span></li> <li><span style="text-decoration: line-through;">"Title" for every title node in the document</span></li> <li>The contents of every 'title' node which exists under an 'item' node </li> </ul> <hr /> <h3>Question 11</h3> <ul> <li><span style="text-decoration: line-through;">They all are equally proper methods</span></li> <li><span style="text-decoration: line-through;">str_split($string, strpos($string, "-=-"))</span></li> <li><span style="text-decoration: line-through;">preg_split("-=-", $string);</span></li> <li>explode("-=-" $string); </li> </ul> <hr /> <h3>Question 12</h3> <ul> <li>A String</li> <li><span style="text-decoration: line-through;">An array</span></li> <li>A DomDocument object</li> <li>A URI</li> <li><span style="text-decoration: line-through;">A Database resource </span></li> </ul> <hr /> <h3>Question 13</h3> <ul> <li>@$foo</li> <li>&amp;$variable</li> <li>${0x0}</li> <li>$variable</li> <li><span style="text-decoration: line-through;">$0x0 </span></li> </ul> <hr /> <h3>Question 14</h3> <p>I'm pretty unsure here!</p> <ul> <li><span style="text-decoration: line-through;">None of the above</span></li> <li><span style="text-decoration: line-through;">You should not implement permission systems using sessions</span></li> <li><span style="text-decoration: line-through;">Sessions should be cleared of all data and re-populated</span></li> <li>The session key should be regenerated</li> <li><span style="text-decoration: line-through;">The session should be destroyed </span></li> </ul> <hr /> <h3>Question 15</h3> <ul> <li><span style="text-decoration: line-through;">All of the above</span></li> <li>Prepared Statements</li> <li><span style="text-decoration: line-through;">Persistent Connections</span></li> <li><span style="text-decoration: line-through;">Unbuffered Queries</span></li> <li><span style="text-decoration: line-through;">Query escaping </span></li> </ul> <hr /> <h3>Question 16</h3> <p>When attempting to prevent a cross-site scripting attack, which of the following is most important?</p> <p>Answer...</p> <ul> <li><span style="text-decoration: line-through;">Not writing Javascript on the fly using PHP</span></li> <li><span style="text-decoration: line-through;">Filtering Output used in form data</span></li> <li><span style="text-decoration: line-through;">Filtering Output used in database transactions</span></li> <li><span style="text-decoration: line-through;">Writing careful Javascript</span></li> <li>Filtering all input </li> </ul> <hr /> <h3>Question 17</h3> <ul> <li>__get($variable)</li> <li>__call($method, $params)</li> <li><span style="text-decoration: line-through;">__get($method)</span></li> <li>__set($variable, $value)</li> <li><span style="text-decoration: line-through;">__call($method) </span></li> </ul> <hr /> <h3>Question 18</h3> <p>Not very sure here, neither.</p> <ul> <li><span style="text-decoration: line-through;">Sessions on shared hosts are easily hijacked by outside malicious users</span></li> <li><span style="text-decoration: line-through;">All of the above</span></li> <li><span style="text-decoration: line-through;">You cannot use a custom data store in shared hosts</span></li> <li>Session data stored in the file system can be read by other scripts on the same shared host</li> <li><span style="text-decoration: line-through;">Users outside the shared host can access any site which created a session for them </span></li> </ul> <hr /> <h3>Question 19</h3> <ul> <li>md5()</li> <li><span style="text-decoration: line-through;">hash()</span></li> <li><span style="text-decoration: line-through;">fingerprint()</span></li> <li><span style="text-decoration: line-through;">None of the above </span></li> </ul> <hr /> <h3>Question 20</h3> <ul> <li>Disabling of the short_tags PHP.ini directive</li> <li><span style="text-decoration: line-through;">Enabling the asp_tags PHP.ini directive</span></li> <li><span style="text-decoration: line-through;">That you have XPath support enabled in PHP 5</span></li> <li><span style="text-decoration: line-through;">That your XML documents are well-formed</span></li> <li><span style="text-decoration: line-through;">None of the above, PHP can be embedded in XML in all cases. </span></li> </ul> <hr /> <h3>Question 21</h3> <ul> <li>312211</li> <li><span style="text-decoration: line-through;">3312212</span></li> <li><span style="text-decoration: line-through;">11221221</span></li> <li><span style="text-decoration: line-through;">221131</span></li> <li><span style="text-decoration: line-through;">3211122</span> </li> </ul> <hr /> <h3>Question 22</h3> <p>Not sure about the last option.</p> <ul> <li><span style="text-decoration: line-through;">Moving all database credentials into a single file</span></li> <li>Moving all database credentials outside of the document root</li> <li>Restricting access to files not designed to be executed independently</li> <li><span style="text-decoration: line-through;">Setting creditial information as system environment variables</span></li> <li>Using PHP constants instead of variables to store credentials </li> </ul> <hr /> <h3>Question 23</h3> <p>Pretty unsure here ... where is the problem with the code?</p> <ul> <li><span style="text-decoration: line-through;">Cross-Site Scripting Attack</span></li> <li>There is no security hole in this code</li> <li><span style="text-decoration: line-through;">Code Injection</span></li> <li><span style="text-decoration: line-through;">SQL Injection</span></li> <li><span style="text-decoration: line-through;">Cross-Site Request Forgery </span></li> </ul> <hr /> <h3>Question 24</h3> <ul> <li><span style="text-decoration: line-through;">$argv[3];</span></li> <li><span style="text-decoration: line-through;">$argv[2];</span></li> <li><span style="text-decoration: line-through;">func_get_args(3);</span></li> <li>func_get_arg(2);</li> <li><span style="text-decoration: line-through;">func_get_arg(3); </span></li> </ul> <hr /> <h3>Question 25</h3> <p>My answer to "When is it important to validate data coming from an HTML form?" would be: <strong>Always </strong>...</p> <ul> <li><span style="text-decoration: line-through;">Only when the fields are required</span></li> <li><span style="text-decoration: line-through;">Only when accepting file uploads</span></li> <li>Everywhere, except cookies</li> <li><span style="text-decoration: line-through;">Only when accepting forms using an input type of text or a &lt;textarea&gt; field</span></li> <li>None of the above </li> </ul> <hr /> <h3>Question 26</h3> <ul> <li><span style="text-decoration: line-through;">tidy</span></li> <li><span style="text-decoration: line-through;">mysql</span></li> <li>w32api</li> <li><span style="text-decoration: line-through;">curl</span></li> <li>dio</li> </ul> <hr /> <h3>Question 27</h3> <ul> <li><span style="text-decoration: line-through;">None of the above</span></li> <li><span style="text-decoration: line-through;">A fragment of a complete SOAP request</span></li> <li>XML-RPC</li> <li><span style="text-decoration: line-through;">REST</span></li> <li><span style="text-decoration: line-through;">SOAP</span></li> </ul> <hr /> <h3>Question 28</h3> <ul> <li>array_split()</li> <li>split()</li> <li><span style="text-decoration: line-through;">string_split()</span></li> <li>preg_match_all()</li> <li>explode() </li> </ul> <hr /> <h3>Question 29</h3> <p>I went with the last one, but the first two work as well.</p> <ul> <li>/^[hp1-5]*\-.*/i</li> <li>/[hp1-5]*\-.?/</li> <li><span style="text-decoration: line-through;">/[hp][1-5]*\-.*/</span></li> <li><span style="text-decoration: line-through;">/[PhP]{3}[1-5]{2,3}\-.*$/</span></li> <li>/[a-z1-5\-]*/ </li> </ul> http://bigwhoop.ch/artikel/28/2009-07-07/Some-ZCE-Mock-Exam-Questions info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/28/2009-07-07/Some-ZCE-Mock-Exam-Questions Tue, 07 Jul 2009 11:01:52 +0200 Die schnelle Website startet vorne, nicht hinten Caching, Refactoring, Mikro-Optimierungen. Viele Programmierer konzentrieren sich bei Geschwindigkeitsoptimierung stehts auf das Backend. Dabei geht bei den meisten "herkömmlichen" Websites die meiste Zeit im Frontend verloren. <p><strong>Caching, Refactoring, Mikro-Optimierungen. Viele Programmierer konzentrieren sich bei Geschwindigkeitsoptimierung stehts auf das Backend. Dabei geht bei den meisten "herkömmlichen" Websites die meiste Zeit im Frontend verloren.</strong></p><p>Auf Grund diverser Posts auf <a class="DefaultLink" href="http://stackoverflow.com" target="_blank">stackoverflow.com</a> und in diversen Foren, auf Grund Googles Fettn&auml;pfchenbeitrag zum Thema "<a class="DefaultLink" href="http://code.google.com/intl/de-DE/speed/articles/optimizing-php.html" target="_blank">Geschwindigkeitsptimierung in PHP</a>" und einem Artikel von Nils Langner auf phphatesme.com hinsichtlich <a class="DefaultLink" href="http://www.phphatesme.com/blog/allgemein/mikro-optimierung/trackback/" target="_blank">Mikro-Optimierung in PHP</a>, entschloss ich mich, betiteltes Thema aufzugreifen. :-)</p> <p>Bei mir gibt es mal grunds&auml;tzlich eine Devise: <strong>Zuerst Wartbarkeit, danach Geschwindigkeit</strong>!</p> <p>Dieser Leitfaden zieht sich durch viele Aspekte meines Programmierens: Ich vermeide zum Beispiel kryptische Einzeiler, schliesslich muss ich niemandem beweisen wie gut ich bin. Lieber verstehe ich die Funktionalit&auml;t ein Jahr sp&auml;ter direkt auf Anhieb. Dann ziehe ich das Ding mit den Kommentaren konsequent durch. Das ist schon fast ein bisschen pedantisch, aber eine Methode ohne Docblock sieht einfach scheisse aus. Um es mal salopp auszudr&uuml;cken. ;-)</p> <p>Meist sind es PHP Anf&auml;nger die mit Fragen hinsichtlich Geschwindigkeitsoptimierung antraben. Dabei denke ich mir immer (ohne arrogant zu wirken), dass sie sich dann um sowas k&uuml;mmern sollten, wenn es wirklich notwendig wird. Also zu einem sp&auml;teren Zeitpunkt, wenn sie wirklich geschwindigkeitskritische Applikationen schreiben. Ob jetzt n&auml;mlich <code>echo()</code> oder <code>print()</code> schneller ist interessiert im Endeffekt niemanden - auch die Performancetests nicht. Bei sowas geht es nur um subjektives Empfinden, was man als h&uuml;bscher empfindet und ob man in seinem kommenden PHP'ler Leben lieber tausendfach <code>echo()</code> oder <code>print()</code> schreiben m&ouml;chte.</p> <p>Aber eigentlich will ich ja gar nicht auf Optimierung im Backend eingehen. Was mich immer wieder erstaunt ist eher die Tatsache, dass sich viele (sehr viele) Webentwickler einen Deut um ihr Frontend scheren. Dabei geht da, durchschnittlich, viel mehr Zeit verloren als im Backend.</p> <p>Ein Beispiel: Jeder Request f&uuml;r ein eingebundenes Bild, eine CSS- oder JavaScript-Datei braucht vergleichsweise viel Zeit. Ein HTTP-Request muss gesendet werden, der Server muss ihn verarbeiten und der Client die Antwort verwerten. Besonders schlimm wird es dann, wenn keine ordentlichen Headers mitgeschickt und die Dateien deshalb vom Browser nicht gecachet werden. Man denke mal an ein 500 KiB Foto das bei jedem Seitenaufruf geladen werden muss ... autsch!</p> <p>Vor etwa einem Jahr las ich Yahoo!'s "<a class="DefaultLink" href="http://developer.yahoo.com/performance/rules.html" target="_blank">Best Practices for Speeding Up Your Web Site</a>". Damals noch ein 12-Punkte-, heute ein 34-Punkte-Programm mit n&uuml;tzlichen Tipps zum Beschleunigen von Websites. Dabei geht es genau darum, worauf ich eigentlich hinaus will: <strong>Programmierer, schaut euch euer Frontend an!</strong></p> <p>Ich kann jedem Entwickler nur raten, sich die Punkte mal durchzulesen. Nicht alle sind f&uuml;r den individuellen Zweck sinnig, doch bekommt man gute Denkanst&ouml;sse die man nach M&ouml;glichkeiten auch umsetzen sollte.</p> <p>Danach k&ouml;nnt ihr immer noch das Backend optimieren.</p> http://bigwhoop.ch/artikel/27/2009-05-07/Die-schnelle-Website-startet-vorne-nicht-hinten info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/27/2009-05-07/Die-schnelle-Website-startet-vorne-nicht-hinten Thu, 07 May 2009 22:14:19 +0200 Welcome to the Federated Tables of MySQL Heute möchte ich auf ein äusserst nützliches Feature von MySQL eingehen: Federated Tables. Federate(d) heisst zu Deutsch föderiert, verbündet. Ich, als Präsident der Föderierten Tabellen von MyS... lassen wir das. <p><strong>Heute möchte ich auf ein äusserst nützliches Feature von MySQL eingehen: Federated Tables. Federate(d) heisst zu Deutsch föderiert, verbündet. Ich, als Präsident der Föderierten Tabellen von MyS... lassen wir das.</strong></p><p><img src="/img/article_pictures/24/teaser.png" alt="Federated Tables of MySQL and Mysqlasia" width="740" height="270" /></p> <p>Hinter dem Begriff Federated Tables verbirgt sich eine Technik zum Verlinken (/Verb(i|&uuml;)nden/) von Tabellen &uuml;ber die Grenzen einer Datenbank, ja gar eines Datenbankservers, hinweg. Man kann sich das wie einen Symlink unter *NIX, bzw. einer Verkn&uuml;pfung unter Windows vorstellen.</p> <h2>Ein kleines Beispiel<br /></h2> <p>Erstellen wir erst mal zwei kleine Testdatenbanken.</p> <pre name="code" class="sql">CREATE DATABASE `fedtable_1` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE DATABASE `fedtable_2` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;</pre> <p>Anschliessend legen wir eine stinknormale Tabelle in der ersten Datenbank an ...</p> <pre name="code" class="sql">CREATE TABLE `fedtable_1`.`normal` ( `id` INT(3) NOT NULL AUTO_INCREMENT PRIMARY KEY, `firstname` VARCHAR(30) NOT NULL ) ENGINE = MYISAM</pre> <p>... und f&uuml;llen sie mit ein paar Eintr&auml;gen.</p> <pre name="code" class="sql">INSERT INTO `fedtable_1`.`normal` (`id`, `firstname`) VALUES (NULL, 'entry1'), (NULL, 'entry2'), (NULL, 'entry3'), (NULL, 'entry4'), (NULL, 'entry5');</pre> <p>Um jetzt eine Federated Table zu erstellen, m&uuml;ssen wir lediglich die <code>ENGINE</code> auf <code>FEDERATED</code> stellen und einen zus&auml;tzlichen <code>CONNECTION</code> String mitgeben.</p> <pre name="code" class="sql">CREATE TABLE `fedtable_2`.`federated` ( `id` INT(3) NOT NULL AUTO_INCREMENT PRIMARY KEY, `firstname` VARCHAR(30) NOT NULL ) ENGINE=FEDERATED CONNECTION='mysql://root@127.0.0.1/fedtable_1/normal';</pre> <p>Jetzt k&ouml;nnen wir in der Datenbank <code>fedtable_2</code> mit der Tabelle <code>federated</code> wie gewohnt arbeiten. In Wirklichkeit greifen wir aber auf die Tabelle <code>normal</code> der Datenbank <code>fedtable_1</code> zu. Praktisch und einfach.</p> <pre name="code" class="sql">SELECT * FROM `fedtable_2`.`federated`;</pre> <h2>Folgendes gilt es zu beachten</h2> <ul> <li>Die Struktur der <strong>Federated Table muss </strong>der Strukut der <strong>Quelltabelle entsprechen</strong></li> <li>Die <strong>Indexe </strong>sollten aus Performancegr&uuml;nden stets <strong>in beiden Tabellen</strong> gesetzt werden</li> </ul> http://bigwhoop.ch/artikel/24/2009-05-07/Welcome-to-the-Federated-Tables-of-MySQL info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/24/2009-05-07/Welcome-to-the-Federated-Tables-of-MySQL Thu, 07 May 2009 15:32:38 +0200 PHP und Multibyte Strings oder: Meine kleine String Klasse Heute möchte ich kurz darauf eingehen, wie PHP mit Multibyte Strings umgeht und euch meine eigene kleien String Klasse vorstellen <p><strong>Heute möchte ich kurz darauf eingehen, wie PHP mit Multibyte Strings umgeht und euch meine eigene kleien String Klasse vorstellen</strong></p><p>Also ich vor einiger Zeit ein wenig mit Ruby rumspielte, kam ich auf die Idee eine String-Klasse f&uuml;r PHP zu schreiben. Heute st&ouml;berte ich im Blog von Benjamin Hofmann rum und fand dabei seinen <a class="DefaultLink" href="http://ajaveeb.de/string-klasse-version-1-0-1-331" target="_blank">pragmatischen Ansatz f&uuml;r eine String Klasse</a>. Dies motivierte mich auch meinen Versuch zu pr&auml;sentieren.</p> <p>In PHP ist ein String eine Reihe von Bytes, wobei ein Byte einem Zeichen entspricht. Das Problem ist, dass ein Byte nur 256 unterschiedliche Zust&auml;nde haben kann. Ergo k&ouml;nnen nur 256 unterschiedliche Zeichen dargestellt werden. Bis PHP 6 dann gross mit Unicode auftrumpfen wird, m&uuml;ssen sich alle nicht-amerikanischen PHP Entwickler selber helfen.</p> <h2>Multibyte-Strings in PHP<br /></h2> <p>Schauen wir uns z.B. folgendes Code-Snippet in einer UTF-8 Datei (womit wir ja hoffentlich alle arbeiten) an:</p> <pre name="code" class="php">echo strlen('&auml;');</pre> <p>Die Ausgabe ist nicht etwa <code>1</code>, sondern <code>2</code>, da zur Speicherung das &auml;-Zeichens zwei Bytes ben&ouml;tigt werden. Als Abhilfe stehen drei M&ouml;glichkeiten zur Verf&uuml;gung.</p> <h3>mbstring Erweiterung<br /></h3> <pre name="code" class="php">echo mb_strlen('&auml;'); // 1</pre> <p>Die <code>mbstring</code> Erweiterung wird direkt mit PHP ausgeliefert und bietet Multibyte-Alternativen f&uuml;r viele native String Funktionen. Die Portierbarkeit ist dadurch ziemlich gut, allerdings werden nicht sehr viele Character Sets unterst&uuml;tzt. Mit der Konfigurationsdirektive <code>mbstring.func_overload</code> lassen sich ausserdem die nativen String Funktionen durch alle vorhandenen <code>mbstring</code>-&Auml;quivalente "&uuml;berladen" (an Stelle von <code>strpos()</code> wird automatisch&nbsp; <code>mb_strpos()</code> aufgerufen). <code>mbstring</code> eignet sich dadurch sehr gut zum Arbeiten mit Strings.</p> <h3>iconv Erweiterung</h3> <pre name="code" class="php">echo iconv_strlen('&auml;'); // 1</pre> <p>Die <code>iconv</code> Erweiterung wird standardm&auml;ssig nicht mit PHP ausgeliefert und ist deshalb auch nicht auf allen Systemen automatisch vorhanden. Ausserdem gibt es wenige Funktionen zum Arbeiten mit Multibyte-Stringen. Weil die <code>iconv</code> Erweiterung aber viele Character Sets unterst&uuml;tzt, eignet sie sich hervorragend zum Konvertierten von einem Encoding ins andere.</p> <h3>UTF-8 Dekodierung</h3> <pre name="code" class="php">echo strlen(utf_decode('&auml;')); // 1</pre> <p>Solange eine Seite - und damit meine ich sowohl Code als auch Files, Datenbank, Formulardaten, etc. - in UTF-8 betrieben wird, ist die Benutzung der nativen String Funktionen relativ sicher m&ouml;glich. Man sollte einfach schauen, dass die UTF-8 Strings zuerst mit <code>utf8_decode()</code> in ISO-8859-1 Strings konvertiert werden.</p> <p>Auf der n&auml;chsten Seite geht es weiter mit meiner String Implementierung ...</p><h2>Mein Ansatz<br /></h2> <p>In Ruby sind alle Strings Objekte. Ich mag diesen Ansatz sehr, da man dadurch sehr leserlich arbeiten kann (Stichwort Method-Chaining). Deshalb habe ich mich bei der Umsetzung etwas an Ruby orientiert.</p> <p>Die Version 1.0 (wird bestimmt noch erweitert) wird folgendermassen angewendet:</p> <pre name="code" class="php">// Default encoder for all future String objects. // Default is String::ENCODER_MBSTRING. String::setDefaultEncoder(String::ENCODER_ICONV); // Default encoding for all future String objects. // Default is UTF-8. String::setDefaultOutputEncoding('utf-8'); $s = new String('H&auml;nschen Klein'); $s-&gt;dump() // H&auml;nschen Klein &nbsp;-&gt;concat(', ging allein ...') &nbsp;-&gt;dump() // H&auml;nschen Klein, ging allein ... &nbsp;-&gt;reverse() &nbsp;-&gt;dump() // ... niella gnig ,nielK nehcsn&auml;H &nbsp;-&gt;reverse() &nbsp;-&gt;capitalize() &nbsp;-&gt;dump(); // H&Auml;NSCHEN KLEIN, GING ALLEIN ... echo $s-&gt;length; // 31 echo $s-&gt;getLength(); // 31 echo count($s); // 31 echo strlen($s); // 32 echo mb_strlen($s, 'UTF-8'); // 31 $s = new String('Hans hat %d %s'); $s-&gt;format(12, 'Eier') &nbsp;-&gt;dump() // Hans hat 12 Eier &nbsp;-&gt;sub(0, $s-&gt;pos(' hat')) &nbsp;-&gt;dump(); // Hans</pre> <p>Und hier nun der komplette Code:</p> <pre name="code" class="php">class StringException extends Exception {} class String implements ArrayAccess, Countable { const ENCODER_ICONV = 'iconv'; const ENCODER_MBSTRING = 'mbstring'; /** * The default multibyte extension to use * for encoding string * * @var string */ protected static $_defaultEncoder = self::ENCODER_MBSTRING; /** * The default output encoding * * @var string */ protected static $_defaultOutputEncoding = 'UTF-8'; /** * The string value * * @var string */ protected $_string = ''; /** * The extension used to handle multibyte strings * * @var string */ protected $_encoder = null; /** * The encoding of the output string * * @var string */ protected $_outputEncoding = null; /** * The internal encoding to handle strings with * * @var string */ protected $_internalEncoding = 'UTF-8'; /** * Set the default output encoding * * @param string $v */ public static function setDefaultOutputEncoding($v) { self::$_defaultOutputEncoding = $v; } /** * Set the default output encoding * * @param string $v */ public static function setDefaultEncoder($v) { if (!in_array($v, array(self::ENCODER_ICONV, self::ENCODER_MBSTRING))) { throw new StringException('Not supported encoder: ' . $v); } self::$_defaultEncoder = $v; } /** * Constructor * * @param string $v */ public function __construct($v = null, $outputEncoding = null, $internalEncoding = null, $encoder = null) { if (null === $outputEncoding) { $outputEncoding = self::$_defaultOutputEncoding; } $this-&gt;setOutputEncoding($outputEncoding); if (null !== $internalEncoding) { $this-&gt;_internalEncoding = $internalEncoding; } if (null === $encoder) { $encoder = self::$_defaultEncoder; } $this-&gt;_encoder = $encoder; if (null !== $v) { $this-&gt;set($v); } } /** * Set string to one value * * @param string $v * @return String */ public function set($v) { $this-&gt;clear() -&gt;concat($v); return $this; } /** * concat a value to the string * * @param string $v * @return String */ public function concat($v) { switch ($this-&gt;_encoder) { case self::ENCODER_MBSTRING: $this-&gt;_string .= mb_convert_encoding($v, $this-&gt;_internalEncoding, mb_detect_encoding($v)); break; default: // We have to use mb_detect_encoding() here as well ... don't say a word, psst! $this-&gt;_string .= iconv(mb_detect_encoding($v), $this-&gt;_internalEncoding, (string)$v);; break; } return $this; } /** * Get the string value * * @return string */ public function get($outputEncoding = null) { if (null === $outputEncoding) { $outputEncoding = $this-&gt;_outputEncoding; } return $this-&gt;convert($outputEncoding); } /** * Clear the string value * * @return String */ public function clear() { $this-&gt;_string = ''; return $this; } /** * Dump the string with it's real * length in a given encoding * * @param string $outputEncoding * @return String */ public function dump($outputEncoding = null) { //dump the var in xdebug style if (extension_loaded('xdebug')) { $o = sprintf( "&lt;pre class='xdebug-var-dump' dir='ltr'&gt;&lt;small&gt;string&lt;/small&gt; &lt;font color='#cc0000'&gt;'%s'&lt;/font&gt; &lt;i&gt;(length=%d)&lt;/i&gt;%s&lt;/pre&gt;", $this-&gt;get($outputEncoding), $this-&gt;getLength(), PHP_EOL ); } //dump the var in php's default way else { $o = sprintf( "string '%s' (length=%i)", $this-&gt;get($outputEncoding), $this-&gt;getLength() ); } echo $o; return $this; } /** * Dump the string with PHP's var_dump() * function * * @param string $outputEncoding * @return String */ public function dumpRaw($outputEncoding = null) { var_dump($this-&gt;get($outputEncoding)); return $this; } /** * Set the output encoding * * @param string $v * @return String */ public function setOutputEncoding($v) { $this-&gt;_outputEncoding = (string)$v; return $this; } /** * Create a new instance of String * for a given value * * @param string $v * @return String */ public function populate($v) { return new self($v, $this-&gt;_outputEncoding, $this-&gt;_internalEncoding); } /** * Convert the string from one to * another encoding * * @param string $toEncoding * @param string $fromEncoding * @return string */ public function convert($toEncoding = null, $fromEncoding = null) { if (null === $toEncoding) { $toEncoding = $this-&gt;_outputEncoding; } if (null === $fromEncoding) { $fromEncoding = $this-&gt;_internalEncoding; } switch ($this-&gt;_encoder) { case self::ENCODER_MBSTRING: return mb_convert_encoding($this-&gt;_string, $toEncoding, $fromEncoding); default: return iconv($fromEncoding, $toEncoding, $this-&gt;_string); } } /** * Return the count of characters * in the string (not the count of bytes) * * @param string $outputEncoding * @return int */ public function getLength($outputEncoding = null) { if (null === $outputEncoding) { $outputEncoding = $this-&gt;_outputEncoding; } switch ($this-&gt;_encoder) { case self::ENCODER_MBSTRING: return mb_strlen($this-&gt;get(), $outputEncoding); default: return iconv_strlen($this-&gt;get(), $outputEncoding); } } /** * Reverse the string * * PHP does not support multibyte strings * natively. Neither there is a multibyte * version of strrev(). * * @return String */ public function reverse() { $v = $this-&gt;convert('UTF-8'); $v = strrev($v); $v = $this-&gt;convert($this-&gt;_internalEncoding, 'UTF-8'); return $this-&gt;populate($v); } /** * Capitalize the string * * There is no iconv() feature to captialize a * string. So we're always gonna use mb_strtoupper(). * * @return String */ public function capitalize() { return $this-&gt;populate(mb_strtoupper($this-&gt;_string, $this-&gt;_internalEncoding)); } /** * Downcase the string * * There is no iconv() feature to downcase a * string. So we're always gonna use mb_strtolower(). * * @return String */ public function downcase() { return $this-&gt;populate(mb_strtolower($this-&gt;_string, $this-&gt;_internalEncoding)); } /** * Return a subset of a string * * @param int $offset * @param int $length * @return String */ public function sub($offset, $length = null) { switch ($this-&gt;_encoder) { case self::ENCODER_MBSTRING: $v = mb_substr($this-&gt;_string, (int)$offset, $length, $this-&gt;_internalEncoding); break; default: $v = iconv_substr($this-&gt;_string, (int)$offset, $length, $this-&gt;_internalEncoding); break; } return $this-&gt;populate($v); } /** * Return the position of a substring * inside the actual string * * @param int $offset * @param int $length * @return int */ public function pos($needle, $offset = 0) { switch ($this-&gt;_encoder) { case self::ENCODER_MBSTRING: return mb_strpos($this-&gt;_string, $needle, (int)$offset, $this-&gt;_internalEncoding); default: return iconv_strpos($this-&gt;_string, $needle, (int)$offset, $this-&gt;_internalEncoding); } } /** * Format a string * * @return String */ public function format() { $args = func_get_args(); array_unshift($args, $this-&gt;get()); $v = call_user_func_array('sprintf', $args); return $this-&gt;populate($v); } /** * ArrayAccess implementation * * @param int $offset * @return String */ public function offsetGet($offset) { $v = $this-&gt;get(); return $this-&gt;populate($v[(int)$offset]); } /** * ArrayAccess implementation * * @param int $offset * @param string $v * @return String */ public function offsetSet($offset, $v) { $c = iconv_substr($this-&gt;_string, $offset, 1, $this-&gt;_internalEncoding); $bytes = strlen($c); $s = iconv_substr($this-&gt;_string, 0, $offset, $this-&gt;_internalEncoding) . $v . iconv_substr($this-&gt;_string, $offset + $bytes, mb_strlen($this-&gt;_string, $this-&gt;_internalEncoding), $this-&gt;_internalEncoding); $this-&gt;set($s); return $this; } /** * ArrayAccess implementation * * @param int $offset * @return String */ public function offsetUnset($offset) { $s = $this-&gt;get(); unset($s[(int)$offset]); $this-&gt;set($s); return $this; } /** * ArrayAccess implementation * * @param int $offset * @return bool */ public function offsetExists($offset) { $s = $this-&gt;get(); return isset($s[(int)$offset]); } /** * Countable implementation * * @return int */ public function count() { return $this-&gt;getLength(); } /** * @see String::get() */ public function __toString() { return $this-&gt;get(); } /** * Access control for public properties * * @param string $k * @return mixed */ public function __get($k) { switch ((string)$k) { case 'length': return $this-&gt;getLength(); default: return $this-&gt;$k; } } }</pre> http://bigwhoop.ch/artikel/26/2009-04-07/PHP-und-Multibyte-Strings-oder-Meine-kleine-String-Klasse info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/26/2009-04-07/PHP-und-Multibyte-Strings-oder-Meine-kleine-String-Klasse Tue, 07 Apr 2009 15:59:31 +0200 count() in for-Schleifen Eine kleine Benchmark und eine Plädoyer für eine neue Notation <p><strong>Eine kleine Benchmark und eine Plädoyer für eine neue Notation</strong></p><p>Als Appetizer etwas Code. ;-)</p> <pre name="code" class="php">$a = array('foo', 'bar', 'lala'); for ($i = 0; $i &lt; count($a); $i++) { // ... }</pre> <p>Es kommt selten vor, dass ich sowas &uuml;berhaupt brauche, da in diesen F&auml;llen foreach() viel einfacher ist. Dennoch kann es vorkommen, dass eben diese Notation erw&uuml;nscht ist.</p> <p>Durch einen Kommentar auf <a class="DefaultLink" href="http://stackoverflow.com">StackOverflow</a> bin ich auf folgenden Ansatz gestossen.</p> <pre name="code" class="php">$a = array('foo', 'bar', 'lala'); for ($i = 0, $c = count($a); $i &lt; $c; $i++) { // ... }</pre> <p>Ich kannte diese Notation nicht und habe deshalb bei gr&ouml;sseren Arrays stehts die Gr&ouml;sse in einer separaten Zeile ausgelesen. Etwa so ...</p> <pre name="code" class="php">$a = array('foo', 'bar', 'lala'); $c = count($a); for ($i = 0; $i &lt; $c; $i++) { // ... }</pre> <p>Dies ist anzuraten, da count() ansonsten bei jeder Iteration ausgef&uuml;hrt wird. Folgende kleine Benchmark zeigt die Differenz gut auf.</p> <pre name="code" class="php">foreach (array(1, 100, 1000, 10000, 100000) as $l) { echo '&lt;h1&gt;' . $l . '&lt;/h1&gt;'; $a = range(1, $i); $t1 = microtime(true); for ($i = 0; $i &lt; count($a); $i++) {} echo round((microtime(true) - $t1) * 1000, 2) . 'ms'; echo '&lt;br /&gt;'; $t1 = microtime(true); for ($i = 0, $c = count($a); $i &lt; $c; $i++) {} echo round((microtime(true) - $t1) * 1000, 2) . 'ms'; }</pre> <table class="DefaultTable" border="0"> <tbody> <tr> <th>Gr&ouml;sse</th> <th>Nicht optimiert</th> <th>Optimiert</th> </tr> <tr> <td>1</td> <td>0.03ms</td> <td>0.02ms</td> </tr> <tr> <td>100</td> <td>0.29ms</td> <td>0.03ms</td> </tr> <tr> <td>1'000</td> <td>3.43ms</td> <td>0.27ms</td> </tr> <tr> <td>10'000</td> <td>27ms</td> <td>2.41ms</td> </tr> <tr> <td>100'000</td> <td>272.16ms</td> <td>22.88ms</td> </tr> </tbody> </table> <p>Da diese Werte teils signifikante Unterschiede aufweisen werde ich mir in Zukunft einfach angew&ouml;hnen, stehts die optimierte Notation zu verwenden. So bin ich im Zweifelsfall auf der sicheren Seite und spare sogar eine Zeile Code. ;-)</p> http://bigwhoop.ch/artikel/21/2009-06-22/count-in-for-Schleifen info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/21/2009-06-22/count-in-for-Schleifen Mon, 22 Jun 2009 07:08:32 +0200 Nichts ist wie es scheint Eine Kurzgeschichte über Dateien, Dateiendungen und deren Bedeutung im Internet <p><strong>Eine Kurzgeschichte über Dateien, Dateiendungen und deren Bedeutung im Internet</strong></p><p><img src="/img/article_pictures/16/header.jpg" alt="Nichts ist wie es scheint ..." /></p> <p>Besonders als Webdeveloper kommt man mit vielen verschiedenen Dateitypen in Ber&uuml;hrung. Den Typ einer Datei zu bestimmen ist aber gar nicht so einfach wie es den Anschein macht. Den eine Dateendung sagt rein gar nichts &uuml;ber eine Datei aus und kann so sogar zu gef&auml;hrlichen Sicherheitsl&uuml;cken f&uuml;hren.</p> <p>Aber auch John Doe sollte sich ein wenig auskennen, wenn es um Dateien im Internet geht. Denn auch f&uuml;r ihn gilt: Nichts ist wie es scheint!</p> <h2>Dateien unter Windows</h2> <p>Lasst uns erst mal er&ouml;rtern, wie Microsoft Windows mit Dateien umgeht. Unter Windows hat (fast) jede Datei eine Endung. Von Bildern (<em>.jpg</em>, <em>.gif</em>, etc.) &uuml;ber Videos (<em>.avi</em>, <em>.mpg</em>, ...) zu ausf&uuml;hrbaren Dateien (<em>.exe</em>, <em>.bat</em>, usw.). Doch wieso werden jetzt meine MP3s mit meinem Lieblingsplayer ge&ouml;ffnet?</p> <p>Die Antwort ist ganz einfach: Windows f&uuml;hrt eine Liste mit Assoziationen zwischen Dateiendungen und Programmen. Sobald eine Datei ge&ouml;ffnet werden soll wird in dieser Liste nachgeschaut, welches Programm daf&uuml;r zust&auml;ndig ist, und dieses anschliessend - mit dem Pfad zur Datei als Parameter - aufgerufen. Wurde f&uuml;r die Dateiendung kein Eintrag gefunden, &ouml;ffnet sich ein Dialog, wo der Benutzer ausw&auml;hlen kann, mit welchem Programm er die Datei &ouml;ffnen m&ouml;chte.</p> <p style="text-align: center;"><img style="float: left; margin: 0 10px 10px 0;" src="http://bigwhoop.ch/img/article_pictures/16/oeffnen_mit.png" alt="&quot;&Ouml;ffnen mit&quot;-Dialog" width="150" height="150" /></p> <p>Wenn wir also mal ein bisschen zu viel Freizeit h&auml;tten, k&ouml;nnten wir all unsere MP3s mit der Endung <em>.jpg</em> abspeichern und Windows so konfigurieren, dass JPEGs mit unserem Music Player ge&ouml;ffnet werden. Wir h&auml;tten zwar ein grosses Chaos, w&uuml;rden aber auch schnell merken, dass die Dateiendung nichts &uuml;ber eine Datei aussagt. Also nutzen wir unsere Freizeit doch f&uuml;r Kl&uuml;geres, aber lesen daf&uuml;r vorherigen Satz mindestens zehn Mal. Deal?</p> <p>Obwohl du den Deal gebrochen hast, kehren wir zur&uuml;ck zum Thema und schauen uns an, wie eine Datei im Internet &uuml;berhaupt lokalisiert und abgerufen werden kann.</p> <h2>URI, URL, wtf?<br /></h2> <p>Im Internet ist jede Datei &uuml;ber einen eindeutigen Identifikator erreichbar. Dieser wird URI (Uniform Resource Identifier), oder - im Zusammenhang mit dem HTTP- und FTP-Protokoll - auch URL (Uniform Resource Locator), genannt.</p> <h3>Der Aufbau</h3> <p>Eine URL besteht aus folgenden Teilen:</p> <pre>Schema://[Benutzer[:Passwort]@]Server[:Port][/Pfad][?Anfrage][#Fragmentbezeichner]<var></var></pre> <p>Beispiele:</p> <ul> <li>http://www.example.org</li> <li>ftp://pub:bup@ftp.example.org:21/google/pagerank-source.zip</li> <li>http://test.example.org/index.html#top</li> <li>http://www.example.org/search?q=phphil</li> <li>etc.</li> </ul> <h2>Der Schwindel</h2> <p>Ich habe da mal was vorbereitet ...</p> <p>Schauen wir uns die Datei <a class="DefaultLink" href="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.jpg">http://pub.bigwhoop.ch/faked-pic/CaptainObvious.jpg</a> an.</p> <p style="text-align: center;"><img src="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.jpg" alt="CaptainObvious.jpg" width="150" height="150" /></p> <p>Wie bereits durch die Dateiendung <em>.jpg</em> impliziert, erscheint ein JPEG-Bild. Das liegt allerdings nur daran, dass der Webserver (in unserem Fall ein Apache2 - merken f&uuml;r sp&auml;ter!) bei der Auslieferung den Content-Type <em>image/jpeg</em> mitgeschickt und der Browser daraufhin die Daten als JPEG-Bild interpretiert hat.</p> <p>Schauen wir als n&auml;chstes <a class="DefaultLink" href="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.mp3">http://pub.bigwhoop.ch/faked-pic/CaptainObvious.mp3</a> an. Na los, klick schon drauf! Na, erstaunt? Da kam nicht etwa eine MP3-Datei, sondern das selbe JPEG-Bild wie vorher.</p> <p>Schuld daran ist diese eine kleine Zeile innerhalb eines <em>.htaccess</em>-Files auf dem Server:</p> <pre>AddType image/jpeg .mp3</pre> <p>Dadurch weist der Webserver alle Dateien mit der Endung <em>.mp3</em> mit dem MIME-Type <em>image/jpeg</em> aus. Und da haben wir auch schon das n&auml;chste Stichwort ...</p> <h2>Der MIME-Type<br /></h2> <p>Der MIME-Type, Internet Media Type oder auch Content Type bestimmt den Typ einer Datei im Internet. Dies ist n&ouml;tig, da z.B. der Browser eben nicht wissen kann, welche Daten vom Server daher kommen, wenn wir <a class="DefaultLink" href="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.mp3">http://pub.bigwhoop.ch/faked-pic/CaptainObvious.mp3</a> aufrufen. Auf die Dateiendung kann er sich ja, wie vorhin gelernt, nicht verlassen.</p> <p>Zum Aufbau: Der MIME-Type ist aufgeteilt in zwei Teile ...</p> <pre>&lt;Medientyp&gt;/&lt;Subtyp&gt;</pre> <p>Der Medientyp kategorisiert die MIME-Types grob. M&ouml;gliche Medientypen sind z.B. <em>image</em> (f&uuml;r Bilder), <em>text</em> (f&uuml;r von Menschen lesbare Texte) oder <em>audio</em> (f&uuml;r Musikdateien).</p> <p>Der Subtyp spezifiziert die Untermenge des Medientyps. Beispiele mit <em>text</em>: <em>plain</em> (f&uuml;r Klartext), <em>html</em> (f&uuml;r HTML 4.01 kompatiblen HTML-Code) oder <code>css</code><em> </em>(f&uuml;r Cascading Style Sheets).</p> <h3>Eine Sache der Konfiguration</h3> <p>Wie wir bemerkt haben, wird der Typ einer Datei nicht durch ihre Endung, sondern durch ihren MIME-Type bestimmt. Damit der Webserver (Apache2, remember!) den richtigen MIME-Type mitschicken kann, unterh&auml;lt er eine Liste von Assoziationen zwischen Dateiendungen und MIME-Types. Also &auml;hnlich wie Windows eine Liste zwischen Endungen und Programmen besitzt. Bei einem Apache findet man diese Definitionen &uuml;brigens in der Datei <em>mime.types</em>. Hier ein Auszug ...</p> <pre>image/bmp bmp image/cgm cgm image/gif gif image/ief ief image/jpeg jpeg jpg jpe image/png png</pre> <p>Damit haben wir jetzt eigentlich auch schon den Wert einer Dateiendung er&ouml;rtert: Sie dient (lediglich) zur Herleitung von Verkn&uuml;pfungen.</p> <h2>Thesenerh&auml;rtung</h2> <p>Kommen wir zur&uuml;ck auf das Bildbeispiel (<a class="DefaultLink" href="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.jpg">http://pub.bigwhoop.ch/faked-pic/CaptainObvious.mp3</a>) von vorhin. Anhand dessen will ich noch ein paar Beispiele aufzeigen, die versinnbildlichen, dass die Dateiendung (und damit &uuml;brigens auch der Dateipfad) keinen Aufschluss &uuml;ber den Typ einer Datei geben k&ouml;nnen.</p> <h3>Der Programmierer wars ...<br /></h3> <p>Ein weiterer Weg um einen MIME-Type zu setzen ist die Verwendung einer Server-seitigen Programmier-/Scriptsprache. Hier ein kleines Beispiel in PHP.</p> <pre name="code" class="php">//CaptainObvious.php header('content-type: image/jpeg'); echo file_get_contents('CaptainObvious.jpg');</pre> <p>Dazu das Beispiel in der Praxis: <a class="DefaultLink" href="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.php">http://pub.bigwhoop.ch/faked-pic/CaptainObvious.php</a>.</p> <p style="text-align: center;"><img src="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.php" alt="CaptainObvious.php" width="150" height="150" /></p> <h3>URL Rewritting<br /></h3> <p>Eigentlich jeder Webserver (meist durch Erweiterungen) bietet die M&ouml;glichkeit, URLs on-the-fly umzuschreiben. Unter Apache heisst das Ding z.B. <a class="DefaultLink" href="http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html">mod_rewrite</a>.</p> <p>Am besten versteht man URL Rewritting anhand ein paar Beispielen:</p> <ul> <li>Alle .html-Seiten nach .php umschreiben <ul> <li>Aus <em>http://example.org/test.html</em> wird <em>http://example.org/test.php</em></li> <li>RewriteRule ^(.+).php$ $1.html</li> </ul> </li> </ul> <ul> <li>Sch&ouml;ne Produktelinks <ul> <li>Aus <em>http://example.org/produkt-12.html</em> wird <em>http://example.org/product.php?id=12</em></li> <li>RewriteRule ^product-([0-9]+).html$ product.php?id=$1</li> </ul> </li> </ul> <p>Zu beachten gilt, dass durch das Umschreiben der URL keine HTTP-Redirect gemacht wird. Der Browser wird also nicht auf eine andere Seite weitergeleitet. Dies zeigt sich auch dadurch, dass sich die Adressezeile des Browser nicht ver&auml;ndert.<br />Okay, dies gilt nat&uuml;rlich nur, solange sich die Domain nicht ver&auml;ndert. Wenn ich alle Anfragen von http://example.org auf http://example.net leite, muss der Browser gezwungenermassen eine neue Anfrage machen.</p> <h2>Fazit<br /></h2> <p>Folgende Erkenntnisse solltet ihr jetzt erlangt haben:</p> <ul> <li>Eine Dateiendung hat keine Relevanz!</li> <li>Programmierer d&uuml;rfen sich nie auf die Dateiendung verlassen!</li> <li>Vertraut nie auf das, was in eures Browsers Adresszeile steht!</li> <li><a class="DefaultLink" href="http://pub.bigwhoop.ch/faked-pic/CaptainObvious.jpg">http://pub.bigwhoop.ch/faked-pic/CaptainObvious.mp3</a> wird zwar im Browser als Bild angezeigt, auf eurem System wird die Datei aber nicht als Bild angesehen!</li> </ul> <p>Danke f&uuml;rs Lesen! :-)</p> http://bigwhoop.ch/artikel/16/2009-01-06/Nichts-ist-wie-es-scheint info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/16/2009-01-06/Nichts-ist-wie-es-scheint Tue, 06 Jan 2009 11:40:26 +0100 VLC Player goes Slapstick Wie man seinen Lieblingserien ein ganz anderes Leben einhaucht. <p><strong>Wie man seinen Lieblingserien ein ganz anderes Leben einhaucht.</strong></p><h2>Und so gehts ...</h2> <ol> <li>Video nach Wunsch im VLC Player &ouml;ffnen. Am besten eines, dass ihr schon kennt. ;-)</li> <li>CTRL + E dr&uuml;cken um in die Erweiterten Einstellungen zu gelangen.</li> <li>Dort unter Videoeffekte / Farbspass / Farbextrahierung <em>FFFFFF </em>eingeben.<br /><img src="../../../img/article_pictures/20/vlc_color.png" alt="VLC Player Farbeinstellung" width="408" height="327" /></li> <li>Auf der Tastatur die Plus-Taste (rechts bei den Zahlen :P) dr&uuml;cken. Die Abspielgeschwindigkeit sollte jetzt auf 150% sein.</li> <li>Viel Spass! ^^</li> </ol> http://bigwhoop.ch/artikel/20/2009-05-28/VLC-Player-goes-Slapstick info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/20/2009-05-28/VLC-Player-goes-Slapstick Thu, 28 May 2009 18:41:37 +0200 "WEEZER have just united the planet...!!" Eine Versinnbildlichung des globalen Dorfes! <p><strong>Eine Versinnbildlichung des globalen Dorfes!</strong></p><p>Als ich heute Abend ein wenig in meiner musikalischen Vergangenheit watete, entdeckte ich die guten, alten WEEZER-Songs des Blue-Albums wieder. &Uuml;ber YouTubes "Related Videos" gelang ich auf das Video von WEEZERs "Island in the Sun".</p> <p style="text-align: center;"> <object width="425" height="344" data="http://www.youtube.com/v/hy4Y20dOlKs&amp;hl=de&amp;fs=1&amp;rel=0" type="application/x-shockwave-flash"> <param name="allowFullScreen" value="true" /> <param name="allowscriptaccess" value="always" /> <param name="src" value="http://www.youtube.com/v/hy4Y20dOlKs&amp;hl=de&amp;fs=1&amp;rel=0" /> <param name="allowfullscreen" value="true" /> </object> </p> <p>Das subtile "Hip, Hip" des Liedes schien dabei einen anderen Zuschauer vor &uuml;ber sechs Monaten zu einem einfach Posting verleitet zu haben:</p> <pre>Hip Hip from Romania</pre> <p>Und seit her haben es ihm gesch&auml;tzte 2000 User, rund um den Globus, gleich getan. Ob aus Peru, Kroation, Israel, dem Irak, aus Frankreich, Kanada, Puerto Rico, der Tschechischen Republik oder aus Brasilien, Deutschland, Slovenien, Rum&auml;nien, Finnland, Singapur, Chile, etc., die WEEZER-Fans sind global vertreten und erfreuen einander mit einem simplen "Hip, Hip"!</p> <p>Einfach grossartig, wenn man merkt, wie die Welt zu diesem globalen Dorf wird, wovon man so viel h&ouml;rt, es aber selten so zu sehen bekommt!</p> <p>In diesem Sinne: Hip, Hip! :-)</p> <p>PS: Hier gehts zu den <a class="DefaultLink" href="http://www.youtube.com/comment_servlet?all_comments&amp;v=hy4Y20dOlKs">Kommentaren</a> (am Ende von Seite 2 beginnt der Wahnsinn ;-))!</p> http://bigwhoop.ch/artikel/19/2009-04-27/WEEZER-have-just-united-the-planet info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/19/2009-04-27/WEEZER-have-just-united-the-planet Mon, 27 Apr 2009 18:21:54 +0200 Custom times on NBA's League Pass Broadband For a swiss fella like me it's pretty annoying to convert the start times on ilp.nba.com to my local time. So here is a small Greasemonkey script which does the trick. <p><strong>For a swiss fella like me it's pretty annoying to convert the start times on ilp.nba.com to my local time. So here is a small Greasemonkey script which does the trick.</strong></p><p>All you need is <a class="DefaultLink" href="https://addons.mozilla.org/de/firefox/addon/748">Greasemonkey</a> (and Firefox) and <a class="DefaultLink" href="../../../js/greasemonkey/nba_ilp_custom_times.user.js">this script</a>!</p> <p>On your first visit on ilp.nba.com after installing the script you'll be asked to enter your time zone by giving an UTC offset. Your input will be stored in a cookie. So if your made a typo, clear your cookies for the domain "ilp.nba.com" and try again. ;-)</p> <h2>Time zones</h2> <p>Here some time zone offsets from UTC.</p> <table class="DefaultTable" border="0"> <tbody> <tr> <th>Time zone</th> <th>UTC offset</th> </tr> <tr> <td>Apia, Upolu, Samoa</td> <td>-11:00</td> </tr> <tr> <td>Honolulu, Oahu, Hawaii, United States</td> <td>-10:00</td> </tr> <tr> <td>Anchorage, Alaska, United States</td> <td>-09:00</td> </tr> <tr> <td>Los Angeles, California, United States</td> <td>-08:00</td> </tr> <tr> <td>Calgary, Alberta, Canada</td> <td>-07:00</td> </tr> <tr> <td>Mexico City, Mexico</td> <td>-06:00</td> </tr> <tr> <td>New York City, United States</td> <td>-05:00</td> </tr> <tr> <td>Santiago, Chile</td> <td>-04:00</td> </tr> <tr> <td>S&atilde;o Paulo, Brazil</td> <td>-03:00</td> </tr> <tr> <td>Fernando de Noronha, Brazil</td> <td>-02:00</td> </tr> <tr> <td>Praia, Cape Verde</td> <td>-01:00</td> </tr> <tr> <td>London, United Kingdom</td> <td>+00:00 (= UTC)<br /></td> </tr> <tr> <td>Paris, France</td> <td>+01:00</td> </tr> <tr> <td>Cairo, Egypt</td> <td>+02:00</td> </tr> <tr> <td>Moscow, Russia</td> <td>+03:00</td> </tr> <tr> <td>Dubai, United Arab Emirates</td> <td>+04:00</td> </tr> <tr> <td>Karachi, Pakistan</td> <td>+05:00</td> </tr> <tr> <td>Mumbai, India</td> <td>+05:30</td> </tr> <tr> <td>Kathmandu, Nepal</td> <td>+05:45</td> </tr> <tr> <td>Dhaka, Bangladesh</td> <td>+06:00</td> </tr> <tr> <td>Rangoon, Myanmar</td> <td>+06:30</td> </tr> <tr> <td>Jakarta, Indonesia</td> <td>+07:00</td> </tr> <tr> <td>Hong Kong, China</td> <td>+08:00</td> </tr> <tr> <td>Tokyo, Japan</td> <td>+09:00</td> </tr> <tr> <td>Adelaide, South Australia, Australia</td> <td>+09:30</td> </tr> <tr> <td>Sydney, New South Wales, Australia</td> <td>+10:00</td> </tr> <tr> <td>Noum&eacute;a, New Caledonia, France</td> <td>+11:00</td> </tr> <tr> <td>Auckland, New Zealand</td> <td>+12:00</td> </tr> <tr> <td>Nukuʻalofa, Tonga</td> <td>+13:00</td> </tr> </tbody> </table> http://bigwhoop.ch/artikel/18/2009-04-26/Custom-times-on-NBAs-League-Pass-Broadband info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/18/2009-04-26/Custom-times-on-NBAs-League-Pass-Broadband Sun, 26 Apr 2009 13:10:05 +0200 DynDNS Updates mit ddclient (Ubuntu) ddclient ist ein kleiner, feiner Client zum Updaten von DNS-Einträgen. Unter Anderem (jap, gross geschrieben!) lässt er sich auch prima zum Erneuern von DynDNS-Adressen verwenden. Hier eine Kurzanleitung. <p><strong>ddclient ist ein kleiner, feiner Client zum Updaten von DNS-Einträgen. Unter Anderem (jap, gross geschrieben!) lässt er sich auch prima zum Erneuern von DynDNS-Adressen verwenden. Hier eine Kurzanleitung.</strong></p><h3>ddclient installieren</h3> <p> Mit aptitude geht die Installation ratzefatz! </p> <pre name="code">sudo apt-cache update sudo apt-get install ddclient</pre> <h3>Konfiguration anpassen</h3> <p> Die ddclient-Konfiguration findet sich unter <em>/etc/ddclient.conf</em>. Diese Datei also mit deinem Editor nach Wahl (z.B. nano) öffnen und folgendermassen anpassen: </p> <pre name="code">pid=/var/run/ddclient.pid protocol=dyndns2 use=web server=members.dyndns.org login=&lt;benutzername&gt; password=&lt;passwort&gt; &lt;shortdomain1&gt;.dyndns.org &lt;shortdomain2&gt;.is-a-geek.org &lt;shortdomain3&gt;.homelinux.org #etc ...</pre> <p> <code>use=web</code> bewirkt, dass deine aktuelle IP-Adresse über eine externe Website (z.B. http://checkip.dyndns.org/) ermittelt wird. </p> <h3>ddclient als Dienst (Daemon) einrichten</h3> <p> Mit einem Editor die Datei <em>/etc/default/ddclient</em> öffnen und anpassen. </p> <pre name="code">run_daemon="true" daemon_interval="300" #5 Minuten</pre> <p> Die 300 beschreibt den Intervall in Sekunden, in dem ddclient auf eine neue IP-Adresse überprüfen soll. </p> <p> Danach nur noch mit <code>sudo /etc/init.d/ddclient start</code> den Dienst ankicken und das wars. :-) </p> http://bigwhoop.ch/artikel/17/2009-04-19/DynDNS-Updates-mit-ddclient-Ubuntu info@phphil.ch (Philippe Gerber) http://bigwhoop.ch/artikel/17/2009-04-19/DynDNS-Updates-mit-ddclient-Ubuntu Sun, 19 Apr 2009 17:06:24 +0200