Posts filed under 'PHP'
See the gory details in http://bugs.php.net/bug.php?id=43450.
Basically, there are function which expect strings and the implicit _toString() call on an object will leak memory. Testcase:
< ?php
class Foo {
function __toString() {
return 'foo';
}
}
for ($i = 0; $i < 1e5; $i++) {
$o = new Foo;
# leaks
md5($o);
# does not leak
#md5($o->__toString());
# does not leak either way
# strstr($o, 'f');
#strstr($o->__toString(), 'f');
if ($i % 1e3 == 0) {
printf("%u: %1.2f KB\n",
$i, memory_get_usage(true) / 1024);
}
}
November 30th, 2007
I’ve hacked together a little PHP script which allows to filter mysql log files for sql statements issued by specific users.
Basic usage:
php mysqltail.php /var/log/mysql.log userToFilter [orOtherUser]
It can also be used to pipe an existing logfile:
cat mysql.log | php mysqltail.php - userToFilter
Download: http://markus.fischer.name/lab/php/mysqltail.php.txt
September 19th, 2006
One of the often encountered problems when developing application in the web environment is their complex setup. It’s not like a desktop application that you can check out, compile and run the source.
You need a proper server environment where your application can run, the components need to have the required version, etc. Setting up web server is not hard but tuning all required parameters takes time. And usually in a team of developers someone is responsible for the configuration management; and there’s a reason for that.
Because of the resources it takes to set up such an environment, the common sense when developing applications is usually that there’s one server for all developers and that there are one or two fixed checkouts of a project. That’s a bit against the philosophy on how versioning systems are designed to work. Each and every developer should have its own checkout. But with a complex environment it’s not always feasable to have this process. When it takes so much resources to have the central development server fine tuned you can bet it takes even more for local development on the developers computer.
My goal was that we have flexibility:
- have a place were we check out a complte project and multiple (!) developer can work on one checkout (traditional)
- have a place for each developer on the development server where he can check out as many custom web projects as he wants
- make it next to zero work to create new apache configurations for new projects (VirtualHosts, etc.)
I solved this with a small PHP class and some shell scripting, which basically can generate working apache VirtualHosts configuration on the fly. For this we need to know a few things first:
- the path where the apache configuration templates are stored
- the path to the common checked out projects
- the base directory for user specific checked out projects
- where to generate the PHP5 apache configuration
- where to generate the PHP4 apache configuration
To recognize a directory whether it is a project to be enabled for apache we’ve the following rules for the directory name:
.php4|.php5[.extern]
Within the directory name is the distinction whether it’s an PHP4 or PHP5 project. That’s necessary because we’re running two instances of apache for each version of PHP so we can run both versions as apache modules.
The other directive, .extern, tells us that we want to public this project from our development server live on the internet. Why? Well, customers are everthing but patient, so it happens quite often we hand out URLs of our current development state to our customers. This also means we have to generate separate VirtualHost configuration for those projects.
The same rule applies to the user specific project directory, except that we don’t support .extern there, see below we.
Every project generated from those rules may have the following URLs:
project.dev.company.tld
For e.g. project.php4, not accessibe for customers
project.live.company.tld
For e.g. project.php5.extern
And for user specific checkouts:
project.username.dev.company.tld
In the end it’s dead simple. It took me about 2 days to gather the requirements, talk with the other developers how we could approach this and implement the soluation. Thanks to apaches Include *.conf directive it’s really easy to dynamically generate VirtualHosts and tell apache to restart.
Since ever developer within our company should be able to create new VirtualHosts config on demand, I provided a basic web interface which generates the apache configuration and restarts apache. Restarting apache from within PHP was a bit problematc, because you need to
- have the proper permissions to restart apache from user www-data (I’m using Debian)
- take care that running a PHP script which stops apache also terminates this very PHP script
To solve the permission problem I used sudo and creates a sudoers file like this:
Cmnd_Alias WWWEXEC = /data/www/intern/magic-config/generate.sh
www-data ALL = (root) NOPASSWD: WWWEXEC
To properly execute this script I had to put it into background immidiately so it is decoupled from the PHP script:
exec(“sudo /data/www/intern/magic-config/generate.sh&”);
The generate.sh shell script restarts apache.
At the moment I do not plan to release the code for two reasons:
- I would need to get permission from my company, but if someone think he would really benefit from it, I may ask for it
- It may be to specific anyway to our environment
July 12th, 2006
The only way to get a custom User-Agent string to HTTP_Client is by deriving HTTP_Client and overloading the method _createRequest.
Although HTTP_Client with its constructor provides a way to pass custom headers, the User-Agent header is also set inside HTTP_Request (create by HTTP_Client) which overrides any earlier value.
February 24th, 2006
Environment: Windows, CLI, using pdo_odbc.
Here are some observations from my first steps with the new PDO extension.
Good:
- Exception-Safe (with PDO::ERRMODE_EXCEPTION)
I wonder how one could every seriously write good application without exceptions (i.e. proper and predictable error handling)
- Simple, easy API
The API is so easy, it has so less methods and therefore is easy to grasp. It may all back in complex situations but that I cannot tell that at the moment.
Not so good:
- Bound parameters/values not working as expected
I’m not yet sure if it’s because I use pdo_odb or something else. What I tried, I couldn’t get it to working, no matter which way I tried. So I had to revert to using variables direct in the SQL statement.
- Crashes
PDO has the bad habit that it crashes PHP where it can. Since I’m under Windows and I’ve no Windows C IDE I can’t help in debugging this problems myself but can only try to come up with reproduceable scripts. PDO seems to completely go havoc when you use the PDO::FETCH_LAZY attribute on PDO::query(). With havoc I mean that it throws back to you errors which aren’t a direct result of using FETCH_LAZY. I observed that I got two different kind of exceptions (Yes, I do love them) when using FETCH_LAZY. Both were Microsoft Access Driver problems, but they didn’t showed up once I stopped using FETCH_LAZY. One problem was error code 1311 and the other 1310. The former has something to do with running out of memory and the second one with an invalid table id.Then it seems, unreproduceable in small scripts, that it crashes when doing clean up at the end of the script. So basically, you’re doing your thing and when the script ends it gives you the send report to microsoft dialog
February 5th, 2006
Christian Stocker quoted Rob Richards from the PHP internals mailing list on how to extend SimpleXML. Someone needed more information of the structure of the XML document, for example the name of the node. On the list it was suggested to use the DOM extension which can, without too much overhead, import SimpleXML document (which can be re-imported to SimpleXML again).
The solution adviced on the list was to derive a class from SimpleXMLElement, pass this class to the simplexml_load_* function as second parameter.
November 1st, 2005
This is a small patch for current CVS HEAD in PHP which enables the tidy getParent() function which seemed to be forgotten.
Update on 24th of March, 2006: seems it’s necessary to ask the PHP developer with whom to sleep to get a patch finally commited.
Index: php_tidy.h
===================================================================
RCS file: /repository/php-src/ext/tidy/php_tidy.h,v
retrieving revision 1.25
diff -u -r1.25 php_tidy.h
--- php_tidy.h 25 Apr 2005 20:46:16 -0000 1.25
+++ php_tidy.h 15 Jul 2005 09:59:44 -0000
@@ -89,6 +89,7 @@
TIDY_NODE_METHOD(isJste);
TIDY_NODE_METHOD(isAsp);
TIDY_NODE_METHOD(isPhp);
+TIDY_NODE_METHOD(getParent);
ZEND_BEGIN_MODULE_GLOBALS(tidy)
char *default_config;
Index: tidy.c
===================================================================
RCS file: /repository/php-src/ext/tidy/tidy.c,v
retrieving revision 1.65
diff -u -r1.65 tidy.c
--- tidy.c 25 Apr 2005 20:46:16 -0000 1.65
+++ tidy.c 15 Jul 2005 09:59:45 -0000
@@ -291,6 +291,7 @@
TIDY_NODE_ME(isJste, NULL)
TIDY_NODE_ME(isAsp, NULL)
TIDY_NODE_ME(isPhp, NULL)
+ TIDY_NODE_ME(getParent, NULL)
{NULL, NULL, NULL}
};
@@ -1668,6 +1669,30 @@
}
/* }}} */
+/* {{{ proto boolean tidyNode::getParent()
+ Returns the parent node if available or NULL */
+TIDY_NODE_METHOD(getParent)
+{
+ TidyNode parent_node;
+ PHPTidyObj *newobj;
+ TIDY_FETCH_ONLY_OBJECT;
+
+ parent_node = tidyGetParent(obj->node);
+ if(parent_node) {
+ tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
+ newobj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
+ newobj->node = parent_node;
+ newobj->type = is_node;
+ newobj->ptdoc = obj->ptdoc;
+ newobj->ptdoc->ref_count++;
+ tidy_add_default_properties(newobj, is_node TSRMLS_CC);
+ } else {
+ ZVAL_NULL(return_value);
+ }
+}
+/* }}} */
+
+
static void _php_tidy_register_nodetypes(INIT_FUNC_ARGS)
{
TIDY_NODE_CONST(ROOT, Root);
August 12th, 2005
As Sean Coates points out, never trust user data any kind of. He gives a good example on what could slip the developers eye: the PHP_SELF variable. Read his blog for examples and how to cope with it.
May 24th, 2005
For some people it’s fun upgrading php. For me it’s work. This time I had the pleasure of upgrading 4.2.2 to 4.3.9. Unfortunately it did break the behaviour of ob_gzhandler.
For some reason it was decided to modify the behaviour of ob_gzhandler when the client sends no Accept-Encoding header. Prior to this change, the function simple returned the data unmodified if it wasn’t able to detect any support encoding.
After this change, it simply returns false. So this is pretty bad when you use it this way
echo ob_gzhandler($data);
because now all you get back is a blank page.
What client does not send an accept encoding? As it seems some wierd Internet Explorer configration insisting to use the HTTP/1.0 protocol. Or wget. Now tell me this is something people verify nowadays when upgrading a server-side software?
April 6th, 2005
Previous Posts