I realize this update is long overdue, but I’ve been so busy I haven’t been thinking about posting on my blog. I apologize for that, and I’ll try (again) to post more frequent updates. Meanwhile, I thought I’d talk about something that has been taking up some of my time recently. I recently started actively pursuing my writing again, wrapping up my first full length novel. (I have a couple short novels written as well, but this is my first 100k+ piece.) Several of you already know about this, since you’re involved. Others may have seen me tweeting about it, but I hope you’ll still enjoy hearing about it. Read more »
Screening files on push in a git repo
I recently had the need to make sure that files that were pushed to a git repository had a required string in them. It took a few hours, but here’s what I came up with to do it:
#!/bin/sh refname="$1" oldrev="$2" newrev="$3" paths="path/in/repo/" required="REQUIRED_STRING" hashes=( $(git diff-tree -r $newrev -- $paths | awk '{if ($5 == "A" || $5 == "M") print $4}') ) files=( $(git diff-tree -r $newrev -- $paths | awk '{if ($5 == "A" || $5 == "M") print $6}') ) error=0 errors=() for (( c = 0; c < ${#hashes[@]}; c++ )) do check=$(git show ${hashes[$c]} | grep $required | wc -l) if [ "$check" == "0" ] then errors=( "${errors[@]}" ${files[$c]} ) error=1 fi done if [ "$error" == "1" ] then echo echo "The following SQL scripts do not have the required string '$required':" for (( c = 0; c < ${#errors[@]}; c++ )) do echo " ${errors[$c]}" done echo fi exit $error
Save this as ‘update’ in the ‘hooks’ directory of your bare repo, make it executable, and enjoy. Any files in the paths specified that don’t contain the required text will result in a rejected push.
Simple NaNoWriMo API Class
As anyone who knows me probably realizes (because I talk about it incessantly) it’s NaNoWriMo time again. Which means I’m revamping my wordwar tool for this year. This time, I’m giving it a complete overhaul. In the process, I looked at how I was using the API provided by NaNoWriMo, and decided I needed to improve it. After all the coding I’ve done in CakePHP in the last year, I realized there was a very very simple way to do this. Not much to say about it, so here’s the code:
<?php class WordCountApiComponent extends Object { function __call($name, $arguments) { if (count($arguments) == 1) { $xml = $this->_request("http://www.nanowrimo.org/wordcount_api/".$name."/".$arguments[0]); } else { $xml = $this->_request("http://www.nanowrimo.org/wordcount_api/".$name); } return $xml; } private function _request($url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); return new SimpleXMLElement($output); } }
That’s it. Just two methods. (And I could reduce it to 1, but I prefer to keep the CURL logic in it’s own method.)
Using it is just as simple. All NaNoWriMo API methods use either 0 or 1 arguments, and the method names are simply part of the URL. So, to call the ‘wc’ API, that returns the current wordcount for a single user, taking their UID as it’s only parameter, you’d do this:
$uid = 78110; // My UID $api = new WordCountApiComponent(); $wc = $api->wc($uid); echo $wc->uname; // "utoxin" echo $wc->user_wordcount; // '0'
Hope this helps someone! It’s certainly a nice simple way to interface with the API.
More Correct Email from CakePHP
One problem a lot of people have with sending email from PHP in general is properly setting the envelope sender of the message, so that it’s correct in all the headers. This is important because it affects spam filtering rather drastically. Also, some ISPs and other email providers won’t even accept a message if the envelope header is set to an invalid address.
In regular PHP, this is simple to fix. Consider the following example, that sets the from address properly:
<?php $headers = 'From: webmaster@example.com' . "\r\n" . 'Reply-To: webmaster@example.com' . "\r\n" . 'X-Mailer: PHP/' . phpversion(); ); mail( "example@example.com", "Test Message", "This is a test message", $headers, "-fwebmaster@example.com" );
The key here is that last parameter we pass to the function: ‘-fwebmaster@example.com’. That passes a command-line option to sendmail that properly sets the envelope sender. Most people leave that off, because they don’t even realize the need it there.
Okay, so now we know how to do it in raw PHP. How do we do this using CakePHP’s email component? After all, the documentation doesn’t mention anything about that ‘additional parameters’ argument, does it? Or maybe it does. You just have to read the full API docs very carefully. It turns out, if you set the ‘additionalParams’ property of the Email Component, it will pass it on to the mail() function when it calls it. Perfect! So, here’s how to properly initialize the Email Component in CakePHP:
<?php $this->Email->to = 'example@example.com'; $this->Email->subject = 'Test Message'; $this->Email->replyTo = 'webmaster@example.com'; $this->Email->from = 'webmaster@example.com'; $this->Email->additionalParams = '-fwebmaster@example.com'; $this->Email->template = 'test_message'; $this->Email->sendAs = 'both';
And there you have it! The correct way to send email with proper envelope headers from CakePHP. Enjoy the lower spam score that results!
Better Forking for PHP
I recently needed to update a cron job written for CakePHP to make it multi-threaded, so that a job that would take months otherwise could finish in a reasonable amount of time. I originally planned to simply use pcntl_fork() to do this, but upon reading the comments on the function, I quickly realized it would be a major headache to write properly due to database and other socket connections involved in the process.
Read more »
Recent Comments