We have switched from Apache to Nginx a month ago. PHP is running on FastCGI using PHP-FPM. I have just recently tried to debug our app using FirePHP and got a 502 Bad Gateway response from Nginx. It looks like Nginx by default limits the header output. This is the error in Nginx’s error log:
2011/09/21 09:36:16 [error] 816#0: *5 upstream sent too big header while reading response header from upstream,
client: 192.168.56.1, server: v.piclyf.com, request: "GET /pics HTTP/1.1",
upstream: "fastcgi://127.0.0.1:9000", host: "v.piclyf.com", referrer: "http://v.piclyf.com/dashboard"
The fix that I found is to increase the values of fastcgi_buffer_size and fastcgi_buffers. Add these 2 directives to your PHP FastCGI config in Nginx (i.e. /etc/nginx/sites-available/default):
location ~ \.php$ {
root /your/site/root;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
# set these two:
fastcgi_buffer_size 16k;
fastcgi_buffers 4 16k;
}
I was working on a utility class and was playing with the idea of using the id of an object (e.g. NSObject) as a key in NSDictionary. Setting it directly doesn’t work though:
NSObject *obj = [[[NSObject alloc] init] autorelease]; // we'll use this as the key
NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease];
[dict setObject:@"a value" forKey:obj]; // won't work
The above will lead to an exception like this:
NSInvalidArgumentException, reason: '-[NSObject copyWithZone:]: unrecognized selector
sent to instance 0x7ca6160'
The solution I arrived at was to use the string representation of the object. Simply casting the object to NSString will not work though:
[dict setObject:@"a value" forKey:(NSString *)obj]; // same exception
Using a new NSString instance will work however:
NSString *key = [NSString stringWithFormat:@"%@", (NSString *)obj]; // use a new NSString
[dict setObject:@"a value" forKey:key]; // works!
Update
curthard89 from Forrst pointed out that it would be better to use [NSObject hash] instead of typecasting to string. The reason is NSDictionary and NSArray string representations can get really long and would be inefficient. I’m now using this technique:
So I was able to partition a Macbook Pro 2010 (Snow Leopard) using Boot Camp in order to install Windows 7. I just want to point out this possible solution when you get this error when trying to create a partition:
Your Disk Cannot Be Partitioned Because Some Files Cannot Be Moved
Back up the disk and use Disk Utility to format the disk as a single Mac OS Extended (Journaled) volume. Restore your information to the disk and try using Boot Camp Assistant again.
Note that I said this is a possible solution. That means that this may not work for you. Most of the solutions I found on the Internet point to using defrag tools like iDefrag. I didn’t want to go that way cause I really don’t have the money to buy those tools.
Here’s what I did to fix this error:
Clean up the hard drive. Move large files to an external backup disk. There are tools like OmniDiskSweeper to that can help in finding large files.
Reboot and boot up using your Mac OS X Install DVD. (Press C when after the startup sound to boot using the DVD)
Choose Utilities > Disk Utility in the menu and Repair the hard drive.
Restart and try partitioning using Boot Camp again.
I’m not ultimately sure if Step 1 is really required but I don’t have time to test it again.
This is a quick fix for PHP errors like these on a Media Temple DV:
Warning: include_once() [function.include-once]: open_basedir restriction in effect.
I got this a few days ago when trying to setup an app. There are instructions in Media Temple’s site on how to fix this but this set of steps is what worked for me.
Edit or create a vhost.conf file inside this folder: /var/www/vhosts/YOURDOMAIN.COM/conf/. Replace YOURDOMAIN.COM with the domain you wish to configure.
You can get the friends of a Facebook user using this FQL query:
SELECT uid FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = $userId)
This request requires the access token of the user whose friends you want to access. Here’s an example using the Facebook SDK for PHP:
$client = new Facebook(array('appId' => 'YOUR_APP_ID', 'secret' => 'YOUR_APP_SECRET'));
$userId = 123;
$fql = "SELECT uid, first_name, last_name FROM user "
. "WHERE uid in (SELECT uid2 FROM friend where uid1 = $userId)";
$friends = $client->api(array(
'method' => 'fql.query',
'access_token' => 'USER_ACCESS_TOKEN',
'query' => $fql,
));
// we now have an array containing the friends of the user
print_r($friends);
You can look at the user table reference for other fields besides first_name and last_name. Note that there are some fields such as email that require user specific permissions. If the user/friend has not given your app email permissions, chances are you won’t be able to get the email address. For instances like these, you can opt to filter just the friends who have given your app permissions. This can be done using the is_app_user field:
SELECT uid, first_name, last_name FROM user
WHERE is_app_user = 1 AND uid IN (SELECT uid2 FROM friend WHERE uid1 = $userId)
The case with email addresses
From my tests, it looks like it’s more reliable to get the email addresses of friends if you don’t put in any user access token when calling $client->api(). Here’s a complete example of getting a list of friends and getting all their email addresses:
$appId = 'YOUR_APP_ID';
$appSecret = 'YOUR_APP_SECRET';
$userId = 'A_FACEBOOK_USER_ID';
$userAccessToken = 'THE_FACEBOOK_USER_ACCESS_TOKEN';
$client = new Facebook(array('appId' => $appId, 'secret' => $appSecret));
// get all friends who has given our app permissions to access their data
$fql = "SELECT uid, first_name, last_name, email FROM user "
. "WHERE is_app_user = 1 AND uid IN (SELECT uid2 FROM friend WHERE uid1 = $userId)";
$friends = $client->api(array(
'method' => 'fql.query',
'access_token' => $userAccessToken,
'query' => $fql,
));
// make an array of all friend ids
$friendIds = array();
foreach ($friends as $friend) {
$friendIds[] = $friend['uid'];
}
// get info of all the friends without using any access token
$friendIds = implode(',', $friendIds);
$fql = "SELECT uid, first_name, last_name, email FROM user WHERE uid IN ($friendIds)";
$friends = $client->api(array(
'method' => 'fql.query',
'query' => $fql,
// don't use an access token
));
// we should now have a list of friend infos with their email addresses
print_r($friends);
This was tested on CentOS 5.6 on a fresh MediaTemple (dv) setup. I figure it should be the same for any CentOS install. This set of instructions is a result of hours spent on installation troubleshooting; google searches; and trial and errors. Hopefully this can help other people.
Install dependencies
These are needed to enable GraphicsMagick add-ons. In here, I only included what I think are commonly required. But feel free to include other libraries that you need.
We will need to download and compile GraphicsMagick ourselves. It looks like it is not available in yum yet. MediaTemple users are advised to use chroot to prevent noexec and /tmp related errors. Execute these on the console:
# work on a temporary dir of your preference
cd /root/tmp
# download source tarball. See here for other versions: ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/
wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.9.tar.gz
# extract and open the extracted folder
tar -xvf GraphicsMagick-1.3.9.tar.gz
cd GraphicsMagick-1.3.9
./configure --enable-shared
Using --enable-shared above has helped prevent errors like this when installing gmagick through pecl:
Build Error: /usr/bin/ld: /usr/local/lib/libGraphicsMagickWand.a(drawing_wand.o):
relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object;
recompile with -fPIC
After ./configure is done, make sure that the Configured value of the add-ons you need are set to Yes. Also make sure that enable-shared is set to Yes. You can see this at the end part of configure‘s output. It should look like this:
Option Configure option Configured value
------------------------------------------------------------------
Shared libraries --enable-shared=yes yes
Static libraries --enable-static=yes yes
GNU ld --with-gnu-ld=yes yes
Quantum depth --with-quantum-depth=8 8
Delegate Configuration:
BZLIB --with-bzlib=yes no
DPS --with-dps=yes no
FlashPIX --with-fpx=no no
FreeType 2.0 --with-ttf=yes yes
Ghostscript None gs (8.70)
Ghostscript fonts --with-gs-font-dir=default /usr/share/fonts/default/Type1/
Ghostscript lib --with-gslib=no no
JBIG --with-jbig=yes no
JPEG v1 --with-jpeg=yes yes
JPEG-2000 --with-jp2=yes no
LCMS --with-lcms=yes no
Magick++ --with-magick-plus-plus=yes yes
PERL --with-perl=no no
PNG --with-png=yes yes
TIFF --with-tiff=yes yes
TRIO --with-trio=yes no
Windows fonts --with-windows-font-dir= none
WMF --with-wmf=yes no
X11 --with-x= no
XML --with-xml=yes no
ZLIB --with-zlib=yes yes
Next, compile and install:
make
make install
You can then test if GraphicsMagick has been successfully installed by executing commands like:
gm version
Install Gmagick PHP extension
We’ll install gmagick using PECL. MediaTemple users are still advised to use chroot.
pecl install gmagick
If you get an error about gmagick not having a stable version, you can specify the version instead:
pecl install gmagick-1.0.8b2
Next, add extension=gmagick.so to php.ini and restart Apache if necessary. This is outside the scope of this article though. Please Google it if you don’t know how.
And we’re done!
P.S. If you’re having trouble, it might help to look/search for solutions using “ImageMagick” instead. There are fewer resources for GraphicsMagick compared to ImageMagick. I found some articles for ImageMagick that can be used for GraphicsMagick too.
To integrate libraries using namespaces into a Yii Framework project, you can simply use Yii::setPathOfAlias to have the classes autoloaded by Yii when needed. Just specify the root namespace as the alias and the physical location of that root alias as the path.
Using Predis as an example, if we put the code in:
/vendors/predis/lib/Predis
We’ll add it to Yii as an alias named Predis so classes under it can be autoloaded:
Now when we call new Predis\Client(), Yii will look for a file named Client.php in /vendors/predis/lib/Predis. The same holds true for other classes under subfolders (e.g. Predis\Commands\Append).
This is a pattern we’ve been using to organize a big jQuery project that is now composed of 150+ files. When we first started with the project, we kept all page components in their respective jQuery plugins. This was good enough at that time. But as the project grew it became harder and harder to maintain it.
What we did to solve it was go back to basics: use plain JavaScript objects instead of plugins and group them using namespaces.
Plain objects vs plugins
This looks like a step back from making cool plugins but there are actually some benefits. Let’s look at this horizontal slider plugin as an example:
// start slider plugin
(function($) {
var internal = {
init: function($el) {
$el.data('currentPage', 0);
},
showPage: function($el, page) {
// do some fancy animations to show the given page
$el.data('currentPage', 2);
},
currentPage: function($el) {
return $el.data('currentPage');
}
};
$.fn.slider = function(options) {
if (typeof options != 'undefined' && options == 'currentPage')
return internal.currentPage($(this[0]));
return this.each(function() {
if (typeof options == 'undefined')
internal.init($(this));
else if (options == 'showPage')
internal.showPage($(this), arguments[1]);
});
};
})(jQuery);
// and use it like this:
$('#mydiv').slider(); // assume there's a <div id="mydiv"></div> in the HTML
$('#mydiv').slider('showPage', 2);
alert($('#mydiv').slider('currentPage')); // 2
We’re expecting an output like the Coda Slider. The above code is just a skeleton that shows how we’d probably make a horizontal slider plugin. If we were to convert this into a JavaScript object, it would look like this:
// the slider plugin as an Object
(function() {
Slider = {
currentPage: 0,
$el: null, // a public reference to the HTML element we'll work with
// this should be called first before doing anything else
init: function($el) {
this.$el = $el; // save a reference to the element so we can use it later
return this;
},
showPage: function(page) {
// do some animations using this.$el
this.currentPage = page;
}
};
})(jQuery);
// and use it like this
var slider = Object.create(Slider).init($('#mydiv')); // instantiate a new Slider object and pass in the <div>
slider.showPage(2);
alert(slider.currentPage); // 2
This pattern takes advantage of prototypal inheritance (Object.create) to create a new instance of Slider. The advantages of this are:
It’s much cleaner and easier to understand since you’re sort of creating a “class” and one would just have to create a new instance to use it.
It’s not tightly coupled with jQuery. If it ever happens that you’ll have to switch to a different library, it’ll be easier to do so.
Object members are exposed (e.g. currentPage), can easily be inspected and used.
The disadvantages of this are:
A single instance can operate on a single element only. You can easily work around this though.
It’s not a jQuery plugin — it’s not cool (debatable)
Prototypal inheritance
The Object.create() method is not part of JavaScript but is a common pattern used to create a new object whose prototype is the given object. This allows us to inherit the members of Slider into a new (instantiated) object.
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
Now that we have simple objects instead of plugins, we can easily group these into namespaces — objects within objects. We can have a base namespace:
App = {};
And then put our objects under it:
App.Slider = {
// slider code here
};
// util functions under a base Utils namespace
App.Utils = {
foo: function() {
// ...
},
bar: function() {
// ...
}
};
// group related objects under a single namespace
App.SidebarComponents = {
About: {
// ...
},
TagCloud: {
// ...
},
CategoryList: {
// ...
}
};
// create a slider
var slider = Object.create(App.Slider).init($('#div'));
// call a util function
App.Utils.foo();
This now looks at least more organized and maintainable. And you’d have a nice DOM view (FireBug):
What we can learn from this is that jQuery doesn’t really force you to follow a specific design pattern. It’s excellent at DOM manipulation, but it doesn’t provide much outside that. This is actually good, since this means that you can apply your own design on top of it. jQuery should be part of your project and not the backbone of your project.
Speaking of backbone, Backbone.js is a great complement to jQuery that’s definitely worth checking out.
Like one of those bad days, Google doesn’t help. It took me an hour or two to figure out that size is a reserved word in Core Data. Epic fail. You can fix this by escaping size using a hash (#):
PicPing is an iPhone app we just released as part of the Globe MobApp Hunt. It allows you to connect your Facebook, Twitter, Flickr, and Tumblr accounts. You can then take photos and upload it to all your accounts in one go. It is now available for download on the App Store.
I made this using Cocoa Touch / Objective-C. Of all the available social networks, the easiest to integrate was Facebook because of their iOS SDK. The examples were really easy to follow. Tumblr comes next because of their very simple API. I used ASIHTTPRequest for communicating with it. Flickr integration was also a little easier because of ObjectiveFlickr.
Unexpectedly, I spent the longest time with Twitter. There were so many available iOS libraries for Twitter that I couldn’t figure out what to use. And I found most of them to be really hard to understand and start working with. I ended up with this library by Ben Gottlieb for authentication and Twitter posting. I used PlainOAuth and ASIHTTPRequest for communicating with TwitPic. It was a mess but I didn’t have enough time to clean them all up.
To summarize, I wouldn’t have finished all these integrations if it wasn’t for all the awesome open-source libraries. Thanks to all the authors!