Posted (Updated ) in Linux, PHP

I’ve been seeing up an Amazon EC-2 server with Debian Squeeze and used tasksel to install Web Server and Mail Server. Like all things debian, this worked pretty well after the installation completed and everything ‘just worked’ however I wasn’t happy with the default from name and email address assigned to emails sent by PHP – www-data <www-data@my.domain.com>.

I discovered a quick and simple fix to change these defaults for all mail sent with PHP:

Open /etc/php5/apache2/php.ini and set

sendmail_path = '/usr/sbin/sendmail -t -i -fno-reply@my.domain.com -Fno-reply'

You can see a list of sendmail arguments and what they do here.

Restart apache and you’re good to go:

sudo service apache2 restart

Read More »

Posted in Linux, PHP

I’ve been looking for ways to speed up my site recently and came across this interesting article on seamlessly integrating nginx with Apache to handle asset files without requiring a CDN subdomain. This works by checking the requests file extension for .js, .jpg, .pdf etc and if not found, proxies the request to Apache and serves the results.

Benefits

You won’t need to modify all your pages/posts updating asset locations to point to a subdomain! Everything will ‘just work’.

Issues/Drawbacks

There are 2 issues I’ve found with this setup:

  • Because Apache is now running on port 8080, your mod_rewrite redirects will now redirect to that port. You won’t be able to use RedirectMatch anymore, however below is the solution I came up with:
    RewriteEngine on
    RewriteRule ^foo\.php$ http://%{HTTP_HOST}:80/bar.php [R=301,L]
  • You can no longer use .htaccess redirects for any asset files nginx is serving. Instead, use nginx redirects. Below is an example:
    rewrite ^\/foo\.jpg$ http://173.255.221.210/bar.jpg permanent;

    For more information on nginx redirects, see the official documentation.

Read More »

Posted (Updated ) in Javascript, PHP

Even though it hasn’t worked for quite some time now, my previous PHP WebSocket chat application has garnered quite a bit of attention and is still one of my most heavily trafficked posts. As a result I thought I’d provide you all with a working script as of Feb 15, 2012. Also, because I’m your typical lazy developer, I’ll be building on top of other peoples’ work – most notably PHPWebSocket.

You can download the final script here. According to the Wikipedia article on WebSockets, it should work in IE10+, Firefox 7+ and Chrome 14+. Personally I tested with Chrome 17.0.963.46 and Firefox 10.0.1.

I want to stress that this tutorial is designed to be extremely basic and as such does not give alot of functionality out of the box (but provides all the tools required to add more). It’s simply a working example of a PHP-based WebSocket server.

Read More »

Posted (Updated ) in PHP

Last night I was getting a strange error in LemonStand administration area when attempting to edit a product or category:

Fatal error: Maximum function nesting level of ‘100’ reached, aborting! in /path/to/phproad/modules/phpr/helpers/phpr_inflector.php on line 322

If you’re also experiencing this error, it’s caused by XDebug and can be solved by adding

1
ini_set('xdebug.max_nesting_level', 200);

to your config/config.php file.

Thanks to Aleksey Bobkov and EHLOVader for their help in solving this issue. Here is the official LemonStand forum thread on the issue.

Read More »

Posted (Updated ) in Database, Linux, PHP

Tonight I had to move my WPMU install from my local development machine to the live server – this meant a change in installation path which is always a hassle with WordPress. Below I’ll detail my issues and the corresponding fixes in the hopes it will make life easier for others experiencing the same problems.

Redirection to wp-signup.php

First thing I noticed was that when loading the site on a live domain, I’d get instantly redirected to mydomain.com/wp-signup.php?new=mydomain.com. With a bit of Googling I came across this forum thread which recommended adding the following to my wp-config.php:

1
2
define( 'NOBLOGREDIRECT', '' );
define( 'SUBDOMAIN_INSTALL', false );

Don’t do this! It will get the site closer to working order but it’s not going to help you in the long run – especially when you need the other domains working too. Instead here’s what you should be doing:

1
2
3
4
5
6
7
#Dump your DB
mysqldump - u<username> -p<password> -h<host> <dbname> > test.sql
 
#Update folder path to that of the new servers
sed -i "s/path\/to\/install/new\/path\/to\/install/g" test.sql 
#If you installed into localhost/foo/bar/mysite, change that to your live servers domain
sed -i "s/url\/path\/to\/site/www\.domain\.com/g" test.sql

This is pretty standard behavior for moving WordPress sites, however if you load the above dump up on your live domain you’ll probably be greeted with the dreaded Error establishing a database connection.

Error establishing a database connection

Heading to www.domain.com/wp-admin will shed a little more light on the situation – you need to update your wp_blogs table for the main site. WPMU is currently using your development servers URL from this table and ignoring what’s in wp-config.php. To play things safe we’ll update any occurrances of our test servers domain in test.sql:

1
2
#Update your live servers subdomain in wp_blogs to your live servers domain
sed -i  "s/yoursite\.localhost\.com/www\.yourdomain\.com/g" test.sql

This should do the trick. Load that bad boy into your live server and you should be good to go!

Read More »

Posted (Updated ) in Javascript, PHP

JQuery Data Tables is an incredibly handy tool that can make a developers life alot easier – notably by handling search, pagination, filtering and sorting for you. The default functionality is very good, however you’ll often need a bit of customization. This post will detail how to add custom filters and position them to nicely theme with your table. The filters’ state will also be saved so they’ll still be there if you reload the page.

You can see the demo page for this post here. Select a filter and reload the page to see it in action.

Read More »

Posted in Linux, PHP

After upgrading to 11.10 recently, I occasionally noticed fuser firing up and using between 70% and astoundingly 9999% CPU. Googling the issue led me to this post with the solution.

As user grazer explains:

We have the same problem. This is the content of /etc/cron.d/php5 on 11.10:

09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] &amp;&amp; [ -d /var/lib/php5 ] &amp;&amp; find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir fuser -s {} 2&gt;/dev/null \; -delete

And this is the content on 11.04:

09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] &amp;&amp; [ -d /var/lib/php5 ] &amp;&amp; find /var/lib/php5/ -depth -mindepth 1 -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -delete

Spot the difference?

The 11.10 version runs fuser for each PHP session file, thus using all the CPU when there are hundreds of sessions.

After commenting out the 11.10 line and replacing with the 11.04 equivalent, this problem was solved for me aswell. Thanks, grazer!

You can also check out the bug report to keep up to date on this issue. Hopefully a fix will be released quickly.

Read More »

Posted (Updated ) in PHP

I had a bit of an issue with this and the documentation wasn’t of much help so I thought I’d post about the process. I currently have CampaignMonitor and MailChimp modules in the LemonStand marketplace and wanted to allow customers to create subscription forms on their sites that AJAX submit.

Firstly, here is the documentation page on custom events. The docs show that you need two things:

  • A subscribeEvents() method in your module’s setup class containing an addEvent() call.
  • A method containing the code you want to execute, which will be triggered by your event.

I attempted to do the above with the following backend code:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class MyModule_Module extends Core_ModuleBase
{
	public function subscribeEvents()
	{
		Backend::$events->addEvent('MyModule_Module:onSubmit', $this, 'on_submit');
	}
 
	public function onSubmit()
	{
		//...
	}
}

And frontend code:

1
2
3
<form onsubmit="return $(this).sendRequest('MyModule_Module:onSubmit')" action="/" method="post">
	<input type='submit' name='submit' value='Submit' />
</form>

I submitted the form and was greeted with an error message:

An AJAX error occurred: AJAX handler not found.

After a little digging I came across the function excuted when you perform an AJAX query. Important lines are highlighted:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static function execAjaxHandler($name, $controller)
{
	$parts = explode(':', $name);
	if (count($parts) != 2)
		throw new Phpr_ApplicationException("Invalid event handler identifier: $name");
 
	$className = ucfirst($parts[0]).'_Actions';	if (!Phpr::$classLoader->load($className))
		throw new Phpr_ApplicationException("Actions scope class is not found: $className");
 
	$method = $parts[1];
	$isEventHandler = preg_match('/^on_/', $method);	if (!$isEventHandler)
		throw new Phpr_ApplicationException("Specified method is not AJAX event handler: $method");
 
	$obj = new $className();
	if (!method_exists($obj, $method))
		throw new Phpr_ApplicationException("AJAX handler not found: $name");
 
	$obj->copy_context_from($controller);
	try
	{
		$result = $obj->$method();
		$controller->copy_context_from($obj);
		return $result;
	}
	catch (Exception $ex)
	{
		$controller->copy_context_from($obj);
		throw $ex;
	}
}

There’s a couple of things to note here.

  • Your second and third arguments in addEvent() are ignored.
  • _Actions is concatenated onto the end of your class name
  • Your method name must start with on_

With the above in mind, it’s time for some rewriting:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
 
class MyModule_Module extends Core_ModuleBase
{
	public function subscribeEvents()
	{
		Backend::$events->addEvent('MyModule:on_submit', $this, 'on_submit');
	}
}
 
class MyModule_Actions extends Cms_ActionScope
{
	public function on_submit()
	{
		//...
	}
}

That worked like a charm. Good luck to all the module developers for LS out there – I’ve found LemonStand a number of quirks like this and we’ll just have to tackle them one at a time 🙂

Read More »

Posted (Updated ) in Linux, PHP

I’ve was playing with EasyApache in a WHM install recently and after the upgrade I came across a strange error:

SoftException in Application.cpp:357: UID of script "/home/mysite/public_html/index.php" is smaller than min_uid
Premature end of script headers: index.php

Turns out this error is caused by apache being unable to read files added by root to a users public_html folder. A simple fix for this problem is to

chown -R mysite:mysite /home/mysite/public_html

Thanks to user ronniev of eukhost forums for his solution here.

Read More »

Posted (Updated ) in Javascript, PHP

If you’re reading this page (or my blog in general) it’s a pretty safe bet you already have Google+. If you’ve uploaded any photos to Google+ from Chrome or FF, you would also have noticed its snazzy HTML5 file uploader at work. This weekend I took it upon myself to whip up a quick and dirty version of that uploader and share its inner workings with the world.

Google+ Image Uploader
Google+ Image Uploader

Here’s a short video of my uploader at work:

https://www.youtube.com/watch?v=AXx8cu6rxV4

Requirements:

  • PHP4+
  • HTML5-enabled browser (File API – including drag and drop, XHR2)
  • Some images to upload

Disclaimer: Currently only Firefox and Webkit based browsers meet the requirements above. Opera supports the File API and probably XHR2 (I haven’t tested), however it doesn’t have drag and drop so this tutorial won’t work with it. If you’re curious about whether or not IE will work with this tutorial, I’m already laughing at you.

Download the finished script here.

Read More »

Page 4 of 8« First...23456...Last »