A curious error message popped up after I moved my Drupal sites to Nginx. It would only happen on AJAX type changes, but not all of them. I first noticed it when I went to change the author of a node. Then when I tried to change a View I received this error message.
After checking the logs on Nginx and watching what happens using Firebug’s Net panel, it occurred to me that Drupal was making an HTTP “OPTIONS” request.
The other detail is I was using HTTPS (SSL) enforced with the Secure Pages module. It when I was on the HTTPS side of the site those AJAX requests would be HTTP OPTIONS requests to the non-secure side HTTP.
The Solution
The solution was to disable HTTPS for certain pages in the Secure Pages config settings. Why Drupal was making OPTIONS calls to the none secure side of the site is still a mystery.
BTW. When your on the non-secure side, it makes a regular GET or POST request, not an OPTIONS request.
My newest toy I’ve been playing with is Nginx. Getting PHP to work over FastCGI. The performance gain over Apache + mod_php is quite staggering.
Here are a few things to watch out.
Getting PHP v5.2
Some of my apps are not ready to make the jump to PHP 5.3 just yet, so I needed to get a hold of PHP 5.2. In the past I just install the Zend Server CE it would have all the PHP bells and whistles I could ever need. Not anymore, now it’s time to fend for myself.
I’ve added webtatic to my repos and followed his advice to disable PHP 5.3 from his repos you add exclude=php*5.3* to your webtatic.repo file.
Now you can install PHP.
APC Opcode Cache
This waa a little more of struggle as I need to install various things to get it to work. I finally ran pecl install apc and it compiled fine. Then I added a file
/etc/php.d/apc.ini
extension=apc.so
PHP will pick that up and just enable it. Make sure to check that it’s enabled by running phpinfo(). Also you can download the source and extract the file apc.php Throw this on your server and run it in the browser, it will give you a nice rundown about the state of APC and let you know if it’s working.
PHP via FastCGI
There are a few ways to accomplish this and much debate on which is the best way, but I followed the instructions on
It lays it out plain, how to get a FastCGI daemon going. One change I did make though. It has the daemon listening on localhost:9000. I changed my to a socket located at /tmp/phpcgi.socket
Here is the /etc/init.d/php_cgi init script.
Zend Framework
One issue I ran into with Zend Framework, was the location of the sessions folder and the permissions. The default session folder is in /var/lib/php/session this was owned by apache, I just changed the owner:group to nginx:nginx. All was sunshine and roses again.
But for testing if I just did a
print $item->Style it would print just the value C3399
Then I ran across this little advice “You should cast elements to a float (or even string) if you plan on using them…” That made all the difference. So now my code has the (string) casting.
For the top alerts you get after you’ve saved a page or some other event, there is the built in Flashmessenger in Zend Framework, but emanaton has put together a great messenger called PriorityMessenger.
I had it running on one of my sites without issue, but when I tried to get it running on another site I get an error of.
I had placed my PriorityMessenger.php file in: application/views/helpers/PriorityMessenger.php
Then when I tried to access the a controller I received.
Plugin by name 'PriorityMessenger' was not found in the registry; used paths:
Zend_View_Helper_Navigation_: Zend/View/Helper/Navigation/
Support_View_Helper_: /var/www/production/application/modules/support/views/helpers/
Zend_View_Helper_: Zend/View/Helper/
I checked the paths, the class names, etc. still no dice.
You should always use query cache in a production environment. That said, you can easily use it during development, too. Whenever you change a DQL query and execute it the first time Doctrine sees that it has been modified and will therefore create a new cache entry, so you don’t even need to invalidate the cache.
That said, you need to add the following configuration options in
application.ini
If you have a standard Memcached running locally on port 11211 then the following should work.
resources.doctrine.manager.attributes.attr_query_cache.driver = memcache
resources.doctrine.manager.attributes.attr_query_cache.options.servers.host = localhost
resources.doctrine.manager.attributes.attr_query_cache.options.servers.port = 11211
resources.doctrine.manager.attributes.attr_query_cache.options.servers.persistent = true
resources.doctrine.manager.attributes.attr_query_cache.options.compression = false
Don’t store IP addresses in a database as a string like (192.168.10.10). That is just the human readable form of that number. You want to store it in the database as an integer.
MySQL has built in functions to handle converting a dot-notation ip address to an integer equivalent.
But, I needed this type of functionality in PHP itself. Long story short, I’m using Doctrine to handle the relationship that PHP has to the database and I need to convert the human readable dot-notation IP address to the integer style (unsigned integer that is).
PHP’s built in function ip2long comes close, but there is a little bit more to work the magic.
I’ve set up my project on a new server getting prepared to go live. With that comes, moving around some files getting things ready. One thing I’m working on it getting the Zend_Tool command line working.
On the server, I’ve configured
APPLICATION_ENV
to be
production
via
.htaccess
Problem
When I run
zf.sh show doctrine
it errors out because it’s trying to use my “development” DB config rather than the “production” one. I’m not sure how to get around this yet.
Solution
Not pretty, but you have to edit the source of the Zend Framework. The file to edit is ZendFramework/library/Zend/Tool/Project/Context/Zf/BootstrapFile.php
For better or worse, ionCube is an encryption method for those that want to protect their code. A pain the neck for system admins, but some want to protect their PHP code, whatever.
Problem… Zend Optimizer +
Zend Optimizer+ does not play well with ionCube for whatever reason, so it’s really picky on what order they get loaded during startup. It’s important to put the configurations in the correct order, or it will just error out during start up.
Installing ionCube
You’ll want to grab the loader files from here
http://www.ioncube.com/loaders.php
I downloaded and unzipped them to
/usr/local/ioncube
Edit php.ini file
Since ionCube is a Zend Extension and not a Zend Module (what’s the difference? I couldn’t tell you, but there is a different) we need to open up the file
/usr/local/zend/etc/php.ini
and at the very bottom it should look something like this.
; Local Variables:
; tab-width: 4
; End:
[Zend]
zend_extension=/usr/local/ioncube/ioncube_loader_lin_5.2.so
zend.install_dir=/usr/local/zend
zend.conf_dir=/usr/local/zend/etc
zend.ini_scandir=conf.d
Of course the important line is the ioncube line, it’s important that it appears before the other lines.
Big Note about versions
It wasn’t immediately obvious to me, but you need to match your PHP version with the version of ionCube (You can tell I’m using PHP version 5.2).
Verify install
After it’s done you can restart the web server (if the web server doesn’t start check your log files for clues). Then go to the Zend admin panel to see the PHP INFO page. You should see a section that looks like this….
I set up a project just at it says to on this page http://github.com/fmntf/zf-doctrine. It took some doing, but I got it working and was quite happy with my initial results. Then I needed to start a new project, so I just copied all the files, tweaked the DB name was flying with a new project… with one caveat.
One of the modules I created using a YAML file was not getting created in the DB when I ran zf build-project doctrine --reload. It was frustrating, I tried changing a bunch of things.
In the end the whole problem was that the module folder didn’t have a controllers folder and that was it. So I created a controllers folder and then it created the corresponding tables in the db. I think this code has much to do with it