Posts Tagged ‘php’

Simple general data cache for Codeigniter

Thursday, September 24th, 2009

Here’s a very simple and generic data cache class for Codeigniter:

  • since the end of 2008 renames are atomic on both Windows and Linux
  • I use the filemtime with the ttl, this means no extra expiry file
  • the getter doesn’t return the data, but stores it in a buffer
  • values are stored as serialized php files in the CI cache directory
  • use it as a plugin: $CI-<load-<plugin(‘SerCache’); //I didn’t want it to behave like a library

Hope someone finds it useful. A more advanced cache for CI may be found here and another one here.

class SerCache {
public $filename;
private $tempfile;
private $ttl;
private $default_ext = '.ser';
public $buffer;

/**
* Simple data cache
* @param string name filename of the cache file (probably an md5 hash)
* @param mixed ttl time to live in seconds; -1 circumvents caching, 'forever' is infinite
*/
public function __construct($name, $ttl = 'forever')
{
$CI =& get_instance();
$path = $CI->config->item('cache_path');
$this->cache_dir = ($path == '') ? BASEPATH.'cache/' : $path;

$this->ttl = $ttl;
if ($ttl == -1)
return FALSE;
$this->filename = $this->cache_dir.$name.$this->default_ext;
$this->tempfile = $name.getmypid();
}

/**
* Fetch data into $this->buffer
* @return bool FALSE if expired or not set, TRUE otherwise
*/
public function get()
{
if ($this->ttl == -1)
return FALSE;
if ($this->ttl == 'forever')
{
if (!file_exists($this->filename))
return FALSE;
}
else
{
if ((!file_exists($this->filename)) OR (filemtime($this->filename) + $this->ttl < time()))
return FALSE;
}
$this->buffer = unserialize(file_get_contents($this->filename));
return TRUE;
}

/**
* Save serialized value to file
* @param mixed value value to be serialized
*/
public function put($value) {
if ($this->ttl == -1)
return FALSE;
file_put_contents($this->tempfile, serialize($value));
rename($this->tempfile, $this->filename);
}

/**
* Deletes the cachefile
*/
public function destroy() {
if (file_exists($this->filename))
{
unlink($this->filename);
}
}

/**
* Returns the filemtime of the cache file
*/
public function filemtime() {
if (file_exists($this->filename))
return filemtime($this->filename);
return 0;
}
}

Example:

$cache = new SerCache('something', $cacheTTL);
if ($cache->get()) {
$var = $cache->buffer;
} else {
//create var here...
$cache->put($var);
}

Clean/truncate filenames before writing them to a CD/DVD

Sunday, August 23rd, 2009

I’m an old-fashioned IT guy: in filenames I prefer the standard ASCII character set, no spaces, no weird international characters and no meter long names. Before writing a directory to a DVD:

<?php
function cdRename($path, $maxlength) {
$pi = pathinfo($path);
$ext = isset($pi['extension']) ? $pi['extension'] : FALSE;
$fn = $pi['filename'];
$fn = substr($fn, 0, $maxlength);
$fn = str_ireplace(//iso 8859-1 only :((
array('á', 'à', 'ã', 'â', 'é', 'è', 'î', 'í', 'ú', 'u', 'ö', 'õ', 'ô'),
array('a', 'a', 'a', 'a', 'e', 'e', 'i', 'i', 'u', 'u', 'o', 'o', 'o'), $fn);
$npath = $pi['dirname'] . DIRECTORY_SEPARATOR . $fn . ($ext ? '.'.$ext : '');
if ($npath != $path) rename($path, $npath);
}
$it = new RecursiveDirectoryIterator('./');
// RecursiveIteratorIterator - 0: LEAVES_ONLY, 1: SELF_FIRST, 2: CHILD_FIRST
foreach (new RecursiveIteratorIterator($it, 2) as $path) cdRename($path, 170);
?>

This is a PHP cli (shell) script, it truncates filenames (without touching the extension) and removes some international characters, which may pose problems when transferred to ntfs/fat/samba/ext3 etc. Unfortunately PHP is still a crap and if you save this script in UTF-8 then it will not work (at least it did not work for me on ntfs and php 5.2.6), so so far one can only replace iso 8859-1 characters; hope this will change with version 6. The script can also rename directories, since the iterator takes children items first – hope someone finds this useful.

WordPress, first impressions, slight problems

Saturday, April 11th, 2009

I wanted to try WordPress on my host out of curiosity, thought it would be couple of hours, but in the end I ended up tinkering it for a day and I’m totally unsatisfied with the results. Why?

  • the admin interface (compared to blogger) is quite simple; there are many things I couldn’t finetune, except in the template code. It would’ve been nice to include those things at least in a config file (php associative arrays would be totally okay) – so that I don’t end up digging php or looking at the api page…
  • the default new template is, well, not so nice: I find the content:before/after solution for the bulletpoint butt ugly, especially that in IE7 it did not default to the normal for me. I also find the solution for the sidebar annoying, just like the fully uncut header image to mention a few.
  • the default blogger importer totally died on the remote host (no error message, it just ended with one post – and no, this was not an ssl error), while on my local machine it worked. I ended up importing my dumped sql via phpMyAdmin.
  • wp stores some of the paths (with full blown protocol sign) in the db and then renders it into the html code (so instead of “/wp/” we have “http://whatever.com/wp/” which did give me some headaches.
  • the clean_pre builtin formatter function removes all the line break html tags from the preformatted text (formatting.php line 94), which indeed was annoying. Btw html tags inside pre may be uncommon, but are totally valid and I used them in many posts.
  • Wherever I look, maybe it’s just me, but I see php+html+js all mixed together; at least the non-admin “templates” should be nice.

Convert m4a to wav or flac with script

Thursday, January 1st, 2009

For some reason Winamp couldn’t play the Apple Itunes m4a files for me, so I wanted to have a quick solution to convert m4a files to lossless flacs. VLC can write into files as an output, but with that the dumping speed is 1:1, which is not very fast. Basically the solution is just a couple of shell commands, so if you know mplayer, feel free to check the code bellow.

Okay, this is going to be pretty rough: this is a php shell script, I run on Windows, because:

  • I don’t like Cygwin and I totally hate cmd.exe batch scripting (in this case FOR /R and backslashes).
  • I know about the ecmascript and vbscript interpreters and yes, I totally hate those, because they suck compared to plain old Bash and friends.
  • This is a command line php script; I’m on Windows, I registered the .cphp file extension to be handled by php cli, so I just press enter on such file. Believe me, this saved me hours of work, especially at my workplace, where I am using XP and cygwin is broken like hell (I don’t know the admin password to remove it). I know Python is all the hype, but I couldn’t care less.
<?php
$files = explode("\n", `dir /b /o:n *.m4a`);
$mplayer = 'Q:/bin/mplayer/mplayer';
$flac = 'C:/Progra~1/FLAC/flac';
foreach ($files as $file) {
$file = trim($file);
if (!empty($file)) {
echo "Converting $file\n";
shell_exec("$mplayer -vc null -vo null -af volnorm -ao pcm:fast:waveheader:file=\"$file.wav\" \"$file\"");
shell_exec($flac . ' -8 "' . $file . '.wav" ' . str_replace('.m4a.wav', '.flac', $file));
}
}

Getting started with Doctrine – with some headaches

Saturday, October 11th, 2008

I have downloaded Doctrine and started playing with it: no matter how bad I feel about ORMs (mostly for performance considerations), it’s pretty good. The documentation is overwhelming and not the best quality (but at least they do have documentation, which is not granted with all php projects) and sometimes the examples are not very clear, but so far it’s much a bit more fun than plain old CRUD stuff.

Just one fun example:

<?//DOCTRINE
$posts = Doctrine_Query::create()
->select('p.*, u.username, t.name')
->from('Post p')
->leftJoin('p.Tags t')
->leftJoin('p.User u')
->fetchArray();
/*MYSQL*/
SELECT post.id, post.title, user.username,
GROUP_CONCAT(tag.name SEPARATOR ', ') AS tags
FROM post_tag
JOIN tag ON tag_id = tag.id
JOIN post ON post_id = post.id
JOIN user ON post.user_id = user.id
GROUP BY post.id

While I like the MySQL code:

  • Doctrine queries are database agnostic (portability); in this case GROUP_CONCAT is cute, but you can start writing stored procedures in case you end up on MSSQL
  • Less pain with many-to-many relationships (though detect_relations didn’t help much with those)
  • Yaml everwhere: schemas, fixture imports, fixture exports

And some of my problems:

  • the documentation is really half finished (missing sections) and the examples sometimes are very annoying (naming schemes implicate different relationship, unnormalized forms on purpose etc.).
  • detect_relations as far as I know sill can not deal with plurals (if a User has many Posts) – this seems to be a small issue, but it is not, since most of the examples are trying to represent relatinships here.
  • the schema files‘ documentation is very basic and there are places where it contradicts with the Relations section.
  • now it’s may be me, but a slightly more complex table structure and groupbys are a good recipe for headache (the relevant DQL doc part is empty as of this writing).
  • probably it’s me again, but I miss the subqueris with non left joins – I guess it is because old habits die hard, but the object to relation mapping with Doctrine feels like an overkill: the generated queries while are not big or complex, they fail miserably in cases where I can write simple SQL single handedly.