My name is Edward Tanguay. I'm an American software and web developer living and working in Berlin, Germany.


4 hours ago: If you are a developer in Berlin and need to improve your English, I'm looking for groups to teach after work: http://tanguay.info/itenglish.
5 hours ago: As far as I'm concerned, the singularity is already here, every time I wake up twitter tells me something amazing was created while I slept.
5 hours ago: We're not suffering from information overload, we're suffering from faulty filtering.
5 hours ago: Classic literature for free as nicely formatted 1-page or 2-page PDF downloads: http://www.planetebook.com/free-ebooks.asp.
5 hours ago: Yes, when you pour coffee, "a lightning storm of neuronal activity occurs almost across the entire brain": http://is.gd/eWO1T @pholdings.
22 hours ago: If you put two spaces after a period or use underlining for emphasis, you were born before 1980.
22 hours ago: Word of the day: infovore, n. an animal with a voracious appetite for information.
yesterday: It's said that on average people use less than 10% of their brain, but I think on average computers use less than 1% of their CPU.
2 days ago: Saturday fun: team drawing on two computers with six-year-old in a shared google doc diagram.
2 days ago: Someday I want to produce a developer podcast called "What's that?" but for now "the developer's life" is a nice genre: http://is.gd/eTURO.
3 days ago: Here's a use-case for datapod format, recording human-readable data that later can be used as a datasource: http://is.gd/eSsLg @pholdings.
PHP One of the most popular, ubiquitous and useful scripting languages.
|
Free PHP library to keep web app safe from malicious input, 2MB or so, easy to use (two lines). |
Tried it out, worked within 5 minutes, nice macros, try it. |
Trying to get my twitter posts to show up on my website, SUCCEED
|
Trying to get my web developer site to pull data from the Amazon REST API, SUCCEED
|
Regex to replace text only outside certain tags This code shows how to search and replace HTML-coded brackets with actual brackets but not withi PRE tags, e.g. if you want to include code examples between your PRE tags. It is also a nice use of preg_replace_callback.
$text = 'This should be <i>italic</i> but <pre>not <i>this</i> since it is in code</pre> and this should be <i>italic</i> again.';
$newText = preg_replace_callback('%<|>|<pre>.*?</pre>%si', compute_replacement, $text); echo $newText; function compute_replacement($groups) { if ($groups[0] == '<') { return '<'; } elseif ($groups[0] == '>') { return '>'; } else { return $groups[0]; } } |
How to get the base physical path in PHP Similar to MapPath in ASP.NET. This line:
echo dirname($_SERVER['SCRIPT_FILENAME']);
returns, e.g. C:/xampplite/htdocs/web/testScripts which can be used to make sure you are including the correct file no matter where you are in the application, e.g. if you are inside file that renders as a graphic or if you are rendering HTML, etc. |
How to use Namespaces in PHP 5.3 The new Namespaces feature in PHP 5.3 solves the problem that arises in large PHP application which have dozens of nested classes with the same name which leads to long class names such as Core_Classes_Marketing_PrintManager so that it does not get confused with e.g. PrintManager classes in other directories. Namespaces solves this by allowing each file to define a namespace which allows you to just say "PrintManager" and it looks through all files with the same namespace. The code below also shows you how to use an alias to access classes in namespaces other than the current one. ![]() Here's how you had to do it before:
index.php:
------------------------------- <?php include_once('marketing/PrintManager.php'); include_once('sales/PrintManager.php'); $pm1 = new Marketing_PrintManager(); echo $pm1 . '<br/>'; $pm2 = new Sales_PrintManager(); echo $pm2 . '<br/>'; ?> PrintManager.php ------------------------------ <?php class Marketing_PrintManager { function __toString() { return 'this is the sales print manager'; } } ?> SalesManager.php ---------------------------------- <?php class Sales_PrintManager { function __toString() { return 'this is the sales print manager'; } } ?> And here's how to do it with namespaces:
index.php: ------------------------------- <?php namespace Marketing; use Sales as S; include 'marketing/PrintManager.php'; include_once('sales/PrintManager.php'); $pm1 = new PrintManager(); echo $pm1 . '<br/>'; $pm2 = new SPrintManager(); echo $pm2 . '<br/>'; ?> PrintManager.php ------------------------------ <?php namespace Marketing; class PrintManager { function __toString() { return 'this is the marketing print manager'; } } ?> SalesManager.php ---------------------------------- <?php namespace Sales; class PrintManager { function __toString() { return 'this is the sales print manager'; } } ?> |
How to use lambdas and closures in PHP 5.3 If you use lambdas in C# or closures in Javascript and want to transfer this approach to your PHP programming, PHP 5.3 now supports this. These examples below show you the syntax to get started, see more examples here. ![]()
//lambda with array_filter $scores = array(89, 87, 65, 98, 100, 99, 87, 82); $a_scores = array_filter($scores, function($s) { return $s >= 90; }); foreach($a_scores as $a_score) { echo $a_score . '<br/>'; } echo '---<br/>'; //store lambda in variable $a_score_filter = function($s) { return $s >= 90; }; $scores = array(89, 87, 65, 98, 100, 99, 87, 82); $a_scores = array_filter($scores, $a_score_filter); foreach($a_scores as $a_score) { echo $a_score . '<br/>'; } echo '---<br/>'; //closure $greater_than_score_filter = function($lowestScore) { return function($s) use ($lowestScore) { return $s >= $lowestScore; }; }; $scores = array(89, 87, 65, 98, 100, 99, 87, 82); $ab_scores = array_filter($scores, $greater_than_score_filter(80)); foreach($ab_scores as $ab_score) { echo $ab_score . '<br/>'; } echo '---<br/>'; |
How to use late static binding in PHP 5.3 Before PHP 5.3 it was often confusing that a reference with self:: to a static variable returned the value of that variable in the highest class in the hierarchy, not in the class you had specified. And this is actually correct, since the classes aren't instantiated and in that sense have no "self". PHP 5.3 introduces the "static::" prefix which allows you to solve this as shown below. ![]()
class Person {
static protected $status = 'this is a person'; static public function getStatus() { return self::$status; } } class Employee extends Person { static protected $status = 'this is an employee'; } echo Employee::getStatus() . '<br/>'; echo '---<br/>'; class Person2 { static protected $status = 'this is a person'; static public function getStatus() { return static::$status; } } class Employee2 extends Person2 { static protected $status = 'this is an employee'; } echo Employee2::getStatus() . '<br/>'; |
How to use the new PHP 5.3 function array_replace The new function array_replace makes it easy to replace items in an array with groups (arrays) of changes. ![]()
$numberNames = array("zero", "UNKNOWN", "two", "UNKNOWN", "four");
$newNumberNames = array(1 => "WAITING", 3 => "three"); $newNumberNames2 = array(1 => "one"); $finalNumberNames = array_replace($numberNames, $newNumberNames, $newNumberNames2); print_r($finalNumberNames); |
How to use the new PHP 5.3 function parse_ini_string The function parse_ini_file is a very useful way to enable an application to hvae a settings file that your website reads from. You can now use parse_ini_string to read ini files out of e.g. the database as strings instead of from files. ![]()
//$ini_array = parse_ini_file('test.ini');
$ini = getIniTextFromDatabase(); $ini_array = parse_ini_string($ini); print_r($ini_array); echo $ini_array['endRecord']; function getIniTextFromDatabase() { $r = ''; $newline = "rn"; $r .= '[general]' . $newline; $r .= 'startRecord = 45' . $newline; $r .= 'endRecord = 99' . $newline; return $r; } |
How to use the new PHP 5.3 function date_add Although this function and its opposite date_sub are still marked as experimental, they can make adding years, days, hours, minutes and seconds to a datetime very easy. ![]()
$date = new DateTime("2009-12-31 16:30:30");
echo 'original date: ' . $date->format("Y-m-d H:i:s").'<br />'; date_add($date, new DateInterval("P5D")); echo 'plus 5 days: ' . $date->format("Y-m-d H:i:s") . '<br/>'; date_add($date, new DateInterval("PT7H")); echo 'plus 7 hours: ' . $date->format("Y-m-d H:i:s") . '<br/>'; date_add($date, new DateInterval("P2DT5H2M")); echo 'plus 2 days, 5 hours, and 2 minutes: ' . $date->format("Y-m-d H:i:s") . '<br/>'; |
Three new minor PHP 5.3 functions: gethostname(), lcfirst() and get_called_class() It's always good to know which useful functions have been added to new language versions. Here are three minor ones I'll be using. ![]()
echo gethostname() . '<br/>'; echo convertPascalToCamelNotation('MainLogger') . '<br/>'; function convertPascalToCamelNotation($name) { return lcfirst($name); } class Person { public function initialize() { echo get_called_class() . '<br/>'; } } class Employee extends Person { } $person = new Person(); $person->initialize(); $employee = new Employee(); $employee->initialize(); |
How to validate an XML file against an XML Schema (.xsd) file The following code shows you how to make sure an XML file has specific elements that occur in a specific order and that the data in them is of a specific type. If the XML file is invalid, it will pass the error from the validator function on to the user. ![]()
index.php
------------------------ //error_reporting(0); libxml_use_internal_errors(true); // enable user error handling $file = 'test.xml'; $schema = 'test.xsd'; $dom = new DOMDocument; $dom->load($file); if ($dom->schemaValidate($schema)) { echo "$file is valid."; } else { echo $file . ' is invalid. The reason is: <span style="color:red">'; $errors = libxml_get_errors(); foreach ($errors as $error) { //var_dump($error); echo $error->message; } libxml_clear_errors(); echo '</span>'; } test.xml -------------------------------- <?xml version="1.0" encoding="ISO-8859-1"?> <shiporder orderid="MS32322"> <orderperson>John Smith</orderperson> <shipto> <name>Jim Smith</name> <address>1212 Ash St.</address> <city>Conwall</city> <state>WA</state> <zipcode>90283</zipcode> <country>USA</country> </shipto> <item> <title>Photoshop Secrets</title> <note>Special Edition</note> <quantity>1</quantity> <price>39.99</price> </item> <item> <title>Photoshop for Beginners</title> <quantity>1</quantity> <price>29.99</price> </item> <item> <title>Photoshop Tricks</title> <quantity>1</quantity> <price>19.99</price> </item> </shiporder> test.xsd ---------------------------------------- <?xml version="1.0" encoding="ISO-8859-1" ?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- definition of simple elements --> <xs:element name="orderperson" type="xs:string" /> <xs:element name="name" type="xs:string" /> <xs:element name="address" type="xs:string" /> <xs:element name="city" type="xs:string" /> <xs:element name="state" type="xs:string" /> <xs:element name="zipcode" type="xs:string" /> <xs:element name="country" type="xs:string" /> <xs:element name="title" type="xs:string" /> <xs:element name="note" type="xs:string" /> <xs:element name="quantity" type="xs:positiveInteger" /> <xs:element name="price" type="xs:decimal" /> <!-- definition of attributes --> <xs:attribute name="orderid" type="xs:integer" /> <!-- definition of complex elements --> <xs:element name="shipto"> <xs:complexType> <xs:sequence> <xs:element ref="name" /> <xs:element ref="address" /> <xs:element ref="city" /> <xs:element ref="state" /> <xs:element ref="zipcode" /> <xs:element ref="country" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="item"> <xs:complexType> <xs:sequence> <xs:element ref="title" /> <xs:element ref="note" minOccurs="0" /> <xs:element ref="quantity" /> <xs:element ref="price" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="shiporder"> <xs:complexType> <xs:sequence> <xs:element ref="orderperson" /> <xs:element ref="shipto" /> <xs:element ref="item" maxOccurs="unbounded" /> </xs:sequence> <xs:attribute ref="orderid" use="required" /> </xs:complexType> </xs:element> </xs:schema> |
How to check if XML is well-formed This function checks if an XML string is well-formed, and if not, returns a helpful line which you can pass on to the user to help him find what he needs to correct in his XML file to make it well-formed. ![]()
index.php:
--------------------------- $xmlContent = file_get_contents('test.xml'); $errorMessage = ''; if (XmlIsWellFormed($xmlContent, &$errorMessage)) { echo 'xml is valid'; $xml = simplexml_load_string($xmlContent); echo '<pre>'; var_dump($xml); echo '</pre>'; } else { echo 'xml is not valid, reason: <span style="color:red">' . $errorMessage . '</span>'; } function XmlIsWellFormed($xmlString, &$message) { libxml_use_internal_errors(true); $doc = new DOMDocument('1.0', 'utf-8'); $doc->loadXML($xmlString); $errors = libxml_get_errors(); if (empty($errors)) { return true; } $error = $errors[ 0 ]; if ($error->level < 3) { return true; } $lines = explode("r", $xmlString); $line = $lines[($error->line)-1]; $message = $error->message . ' at line ' . $error->line . ': ' . htmlentities($line); return false; } test.xml ----------------------------- <?xml version="1.0" encoding="ISO-8859-1"?> <shiporder orderid="MS32322"> <orderperson>John Smith</orderperson> <shipto> <name>Jim Smith</name> <address>1212 Ash St.</address> <city>Conwall</city> <state>WA</state> <zipcode>90283</zipcode> <country>USA</country> </shipto> <item> <title>Photoshop Secrets</title> <note>Special Edition</note> <quantity>1</quantity> <price>39.99</price> </item> <item> <title>Photoshop for Beginners</title> <quantity>1</quantity> <price>29.99</price> </item> <item> <title>Photoshop Tricks</title> <quantity>1</quantity> <price>19.99</price> </item> </shiporder> |
How to parse XML with XSLT This example shows you a simple function that enables you to define an XML file and a XSLT file and get a string back which is the parsed result of the two. ![]()
index.php
---------------------- echo parseXmlAndXslt('test.xml', 'test.xsl'); function parseXmlAndXslt($xmlFile,$xslFile) { $sXml = file_get_contents($xmlFile); $XML = new DOMDocument(); $XML->loadXML( $sXml ); $xslt = new XSLTProcessor(); $XSL = new DOMDocument(); $XSL->load( 'test.xsl', LIBXML_NOCDATA); $xslt->importStylesheet( $XSL ); return $xslt->transformToXML( $XML ); } test.xml ------------------------- <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="test.xsl"?> <books> <specials> <special> <name>PHP Secrets</name> <cost>34.50</cost> </special> <special> <name>Advanced XSLT</name> <cost>15.50</cost> </special> <special> <name>The JQuery Bible</name> <cost>34.50</cost> </special> <special> <name>Advanced JQuery</name> <cost>22.50</cost> </special> </specials> </books> test.xsl ---------------------------- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:output method="html"/> <xsl:template match="/"> The specials of the week are <xsl:for-each select="books/specials/special"> <xsl:value-of select="name"/> <xsl:if test="position()!=last()">, </xsl:if> <xsl:if test="position()=last()-1">and </xsl:if> </xsl:for-each>. </xsl:template> </xsl:stylesheet> |
How to send in parameters from PHP to an XSLT file Many times when transforming XML with XSLT, you need to include data that is not in the XML file itself. You can pass this data in from PHP via XSLT parameters as we do with the variable "$timePeriod" in this example. ![]()
index.php
---------------------- echo parseXmlAndXslt('test.xml', 'test.xsl'); function parseXmlAndXslt($xmlFile,$xslFile) { $sXml = file_get_contents($xmlFile); $XML = new DOMDocument(); $XML->loadXML( $sXml ); $xslt = new XSLTProcessor(); $XSL = new DOMDocument(); $XSL->load($xslFile); $xslt->importStylesheet( $XSL ); $xslt->setParameter('', 'timePeriod', 'week'); return $xslt->transformToXML($XML); } test.xml -------------------- <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="test.xsl"?> <books> <specials> <special> <name>PHP Secrets</name> <cost>34.50</cost> </special> <special> <name>Advanced XSLT</name> <cost>15.50</cost> </special> <special> <name>The JQuery Bible</name> <cost>34.50</cost> </special> <special> <name>Advanced JQuery</name> <cost>22.50</cost> </special> </specials> </books> test.xsl --------------------------- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> <xsl:param name="timePeriod"/> <xsl:output method="html"/> <xsl:template match="/"> The specials of the <xsl:value-of select="$timePeriod"/> are <xsl:for-each select="books/specials/special"> <xsl:value-of select="name"/> <xsl:if test="position()!=last()">, </xsl:if> <xsl:if test="position()=last()-1">and </xsl:if> </xsl:for-each>. </xsl:template> </xsl:stylesheet> |
How to Use PHP Functions from inside XSLT Shows how you can easily use any standard PHP function or any custom PHP function from within an XSLT file. Note that when you do this your XSLT is no longer portable to other platforms (e.g. .NET) but this is often just the trick to give your XSLT some flexibility and power that it lacking, especially when you call PHP functions which send a parameter and look information up in a database, etc. ![]()
index.php
-------------------------- echo parseXmlAndXslt('test.xml', 'test.xsl'); function parseXmlAndXslt($xmlFile,$xslFile) { $sXml = file_get_contents($xmlFile); $XML = new DOMDocument(); $XML->loadXML( $sXml ); $xslt = new XSLTProcessor(); $XSL = new DOMDocument(); $XSL->load($xslFile); $xslt->registerPHPFunctions(); $xslt->importStylesheet( $XSL ); $xslt->setParameter('', 'timePeriod', 'week'); return $xslt->transformToXML($XML); } class businessLogic { public static function addTax($strCost) { $intCost = intval($strCost); return sprintf('%01.2f', $intCost * 1.06); } } test.xml ----------------------------- <?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="test.xsl"?> <books> <specials> <special> <name>PHP Secrets</name> <cost>10.00</cost> </special> <special> <name>Advanced XSLT</name> <cost>15.50</cost> </special> <special> <name>The JQuery Bible</name> <cost>34.50</cost> </special> <special> <name>Advanced JQuery</name> <cost>22.50</cost> </special> </specials> </books> test.xsl ----------------------------- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:php="http://php.net/xsl"> <xsl:param name="timePeriod"/> <xsl:output method="html"/> <xsl:template match="/"> The specials of the <xsl:value-of select="$timePeriod"/> are <xsl:for-each select="books/specials/special"> <xsl:value-of select="php:function('strtoupper', string(name))"/> (<xsl:value-of select="php:function('businessLogic::addTax', string(cost))"/>) <xsl:if test="position()!=last()">, </xsl:if> <xsl:if test="position()=last()-1">and </xsl:if> </xsl:for-each>. </xsl:template> </xsl:stylesheet> |
How to use fopen() to create a proxy site to read any website content into AJAX If your provider allows fopen() on your hosting server, here is a script that allows you to get data from any website into AJAX, Silverlight, Flash, etc. If your provider doesn't support fopen() you can try this curl version.
<?php $url = filter_input(INPUT_GET, 'url',FILTER_SANITIZE_STRING); $validUrlPrefixes[] = "http://tanguay.info"; $validUrlPrefixes[] = "http://www.tanguay.info"; if(beginsWithOneOfThese($url, $validUrlPrefixes)) { echo loadFile($url); } else echo "invalid url"; function loadFile($sFilename) { if (floatval(phpversion()) >= 4.3) { $sData = file_get_contents($sFilename); } else { if (!file_exists($sFilename)) return -3; $rHandle = fopen($sFilename, 'r'); if (!$rHandle) return -2; $sData = ''; while(!feof($rHandle)) $sData .= fread($rHandle, filesize($sFilename)); fclose($rHandle); } return $sData; } function beginsWithOneOfThese($main, $prefixes) { foreach($prefixes as $prefix) { if(beginsWith($main, $prefix)) return true; } return false; } function beginsWith($main, $prefix) { return strpos($main, $prefix) === 0; } ?> |
Function to trim the preceding and trailing blank lines off an array This function uses array_slice to remove the blank lines off the beginning and end of an array, but leaves any internal blank lines. Thanks outis. ![]()
<?php
$lines[] = ' '; $lines[] = ' '; $lines[] = ''; $lines[] = 'first line'; $lines[] = 'second line'; $lines[] = ''; $lines[] = 'fourth line'; $lines[] = ' '; $lines[] = ''; $lines = trimLines($lines); foreach($lines as $line) { echo '[' . $line . ']<br/>'; } function trimLines($lines) { $end = count($lines); for ($start=0; trim($lines[$start]) === ''; ++$start) { if ($start == $end) { return array(); } } for (--$end; trim($lines[$end]) === ''; --$end) {} return array_slice($lines, $start, $end-$start+1); } ?> |














