Posts Tagged ‘cakephp’

Cakephp logger plugin

Wednesday, April 7th, 2010

For one of my projects, I wanted to have a live view of the cake log file in the admin page. What started out as some hacked controller methods, turned into a plugin that can be inserted in any random cake app. Ingredients:

  • a php implementation of the unix tail command, by Paul Gregg
  • a session variable to keep track of what part of the log file has been sent
  • some jquery code (using the periodicalupdater plugin) that adds new lines to a div element as they appear in the log file, scrolls down so the new content becomes visible

The online demo consist of a bare cake ‘install’ with the plugin dropped into the plugins directory. As you can see, there’s no models, views or controllers. Visiting the app will actually log some messages to the debug log. To monitor the log file, visit the plugin path.
I’ve also added two links that lets you add lines to the debug log.

The theoretical advantage of using a plugin is that you can simply drop the code in the plugins directory and voila! it works!
In practice, it’s quite annoying that plugins are similar to, but not exactly structured like cake apps. For example: images and js code should be placed in the vendors folder instead of webroot. Secondly: app_model.php and app_controller.php need to be prefixed by the (singular) plugin name.
Finally, it’s not clear how to integrate the plugin with your actual cake app. Like using the app’s authentication methods to only allow ‘admin’ users to view the log file.

I’m actually not sure a plugin is the right way of implementing an online ‘tail -f’. A component might do a better job. What do you think?

Online demo

The plugin can be downloaded here.

CakePHP Email component

Tuesday, October 20th, 2009

This is quite a simple component that integrates PHPMailer with CakePHP. Save the following code to /app/controllers/components/email.php

<?php 

App::import('Vendor', 'PhpMailer', array('file' => 'phpmailer' . DS . 'class.phpmailer.php'));

/*
    Depends on "unhtml"
*/

class EmailComponent extends PHPMailer
{
	// phpmailer
	var $Mailer = 'sendmail'; // choose 'sendmail', 'mail', 'smtp'
	var $unhtml_bin = '/usr/bin/unhtml';

	// component
	var $controller;

	function startup( &$controller )
	{
		$this->controller = &$controller;
	}

	function renderBody($view)
	{
		// render the view and use its output to set the body text of the email
		$this->Body = $this->controller->render('emails/' . $view, 'email');

		// reset the output of the controller
		$this->controller->output = '';

		// create plain text version of the email
		//
		// create temporary files
		$htmlfile = tempnam(TMP, 'htmlfile');
		$textfile = tempnam(TMP, 'textfile');

		// write html to temporary file
		file_put_contents($htmlfile, $this->Body);

		// convert the html file to plain text
		$cmd = "cat $htmlfile | $this->unhtml_bin > $textfile";
		system($cmd);

		// set the plain text body of the email
		$this->AltBody = file_get_contents($textfile);

		// remove temporary files
		unlink($htmlfile);
		unlink($textfile);
	}
}

?>

In addition to that, make sure phpmailer is installed in /app/vendors/phpmailer. I just extracted the phpmailer archive in /app/vendors/ and created a symlink:

$ tar xzf PHPMailer_v5.0.2.tar.gz
$ ln -s PHPMailer_v5.0.2 phpmailer

Usage
In your controller code, make sure the component is included by adding it to the components array:

var $components = array('Email');

In app/views/layouts, create a new layout called email.ctp. It should contain something like:

<html>
<body>
<?php echo $content_for_layout; ?>
</body>
</html>

Let’s send some emails!
In controller snippet, the renderBody(‘test’) call will create a html email from the view in app/views/users/emails/test.ctp. Additionally, a plain text version will be generated using ‘unhtml’. Unhtml has a package in the Ubuntu / Debian repository.
The action works just like rendering a normal view. The $this->Email object is just an instance of PHPMailer and all PHPMailers’ methods and properties apply.

function testmail()
{
	// *Some notes*
	// Email methods:    http://phpmailer.worxware.com/index.php?pg=methods
	// Email properties: http://phpmailer.worxware.com/index.php?pg=properties
	//
	// Email configuration is done in /app/controllers/components/email.php

	$this->set(compact('some', 'vars'));

	// the email content is just a (html) view in app/views/{controller}/emails/testmail.ctp
	$this->Email->renderBody('test');

	// subject
	$this->Email->Subject = 'Test from example.com';

	// sender
	$this->Email->SetFrom('test@example.com', 'Test');

	// recipients
	$this->Email->AddAddress('joe@example.com', 'Joe');
	$this->Email->AddAddress('jane@example.com', 'Jane');

	// send!
	$this->Email->Send();
}