Kohana: Buffering output on view and rendering it before in the source code

Sometimes you need to hack the order the source code is going to be rendered in a view:

– You want an extra piece of CSS that only aplies to that view, so you think it's not worth creating a single CSS file and including in your mashed file

– You need the same as above for javascript

– Your mind has not completely grasped the way to organize code in MVC  🙂

 

 

Here's a way to do it:

 

in your view you add something like this:

<?php View::start_buffer('head_end'); ?>
<style>
    ::-moz-selection {
        background: #b3d4fc;
        text-shadow: none;
    }

</style>
<?php  View::end_buffer('head_end'); ?>

 

Then, by taking advantage of the wonderful cascading file system that Kohana gives you, you create a View.php class in your application folder that will need to extend the render() function (I'm just adding the relevant changes for this to work; you can have your own extra sauce):

 

class View extends Kohana_View
{
    static public $buffers = array();

    public static function start_buffer($buffer_name)
    {
        self::$buffers[$buffer_name] = '';
        ob_start();
    }

    public static function end_buffer($buffer_name)
    {
        self::$buffers[$buffer_name] = ob_get_clean();
    }

    public function render($file = NULL)
    {
        $rendered = parent::render($file);

        if (! empty(self::$buffers['head_end']))
        {
            $rendered = str_replace('</head>', self::$buffers['head_end'] . '</head>', $rendered);
        }
        return $rendered;
    }

}

 

The buffer names are completely arbitrary, you can make them any way to want.

I leave up to you to improve the way each buffer will be mapped to different locations in the source code.

Drop me a line with your changes

Kohana 3.1.x: Common controller [step 2]

Define parent controller:

 

 

<?php defined('SYSPATH') or die('No direct script access.');

class Controller_Common_Content extends Controller_Template {

 public $template                = '';
 public $template_name           = 'default';
 public $layout                  = 'default';

 public $save_auto_render        = null;

 public $content                 = '{Do something to generate content}';

 public function __construct(Request $request, Response $response) {
 parent::__construct($request, $response);

 $this->session = Session::instance();

 }

 public function before() {

 $this->save_auto_render = $this->auto_render;
 $this->auto_render = false;
 parent::before();
 $this->auto_render = $this->save_auto_render;

 if ($this->auto_render) {
 $this->template = View::factory('template/' . $this->template_name . '/' . $this->layout)
 ->bind('content', $this->content);

 }

 }

 public function action_view_html() {
 $path = $this->request->param('path');

 echo "PATH: $path";
 }

 public function after() {
 parent::after();

 if ($this->auto_render) {
 } else {
 $this->response->headers('content-type', 'application/json');
 echo json_encode($this->content);
 }

 }

}

 

 

 

 

Kohana 3.2.x: Master Template Controller [step 1]

Let's create a content module that will handle both static and dynamic content:

First enable the module:

modules/application/bootstrap.php

Kohana::modules(array(
.
.
'content' => MODPATH . 'content',   // Content module
.
.
));

 

Second, create the master template controller:

modules/content/classes/controller/base/template.php

template_name = Kohana::$config->load('content.template.name');
		$this->template = 'template/'.$this->template_name.'/index';
		parent::before();

		if ($this->auto_render) {
			$this->template->title		= '';
			$this->template->content	= '';

			$this->template->styles		= array();
			$this->template->scripts	= array();
		}

	}

	public function after() {
		if ($this->auto_render) {
			$styles = Kohana::$config->load('content.template.style');
			$scripts = Kohana::$config->load('content.template.script');

			$this->template->styles = array_merge( $this->template->styles, $styles );
			$this->template->scripts = array_merge( $this->template->scripts, $scripts );
		}
		parent::after();;
	}

}

 

Define routes to call the content module:

modules/content/init.php

<?php defined('SYSPATH') or die('No direct script access.');
 
/**
 * Routes for Content
 *
 * @package……Content
 * @category…..Routing
 * @author…….Mauricio Otta
 * @copyright….PortNumber53.com
 */
 
if (! Route::$cache) {
Route::set('homepage-content', '(<language–>"/)()',
array(
  'language' => '(pt-br)',
  'nothing' => '',
))
  ->defaults(array(
  'controller' => 'content',
  'action'     => 'homepage',
));

 Route::set('static-content', '(/).html',
  array(
   'language' => '(pt-br)',
   'path' => '[a-zA-Z0-9_/\.=\-]+',
  ))
  ->defaults(array(
   'controller' => 'content',
   'action'     => 'static',
  ));
}

 

Define the base content controller

response->body('Controller_Base_Content::index();
');
	}

	public function action_homepage() {
		$this->template->content = 'homepage';
	}

	public function action_static() {

		$path = $this->request->param('path');

		if ($filepath = Kohana::find_file('views', 'content/static/' . $path . '.html')) {
			$filepath = 'content/static/' . $path . '.html';
			//$this->template->content = 'static here'.$filepath;

			$content = new Model_Content();
			$latest_content = $content->get_last_posts(10);

			View::bind_global('latest_content', $latest_content);
			$this->template->content = View::factory($filepath, array(
				'latest_content' => $latest_content,
			))->render();

			switch ($path) {
				case 'privacy-policy': $title = 'Privacy Policy'; break;
				default:
					$title = 'unknown: ' . $path;
			}
			$this->template->facebook_og['og:title'] = $title;
			View::set_global('title', $title);
		} else {
			$this->action_dynamic();
		}
	}

	public function action_dynamic() {

		$path = '/'.$this->request->param('path', '');

		$content = new Model_Content();
		$latest_content = $content->get_last_posts(10);
		View::bind_global('latest_content', $latest_content);

		$post = $content->get_post_by_url($path);

		if ($post && $latest_content) {
			$this->template->content = View::factory('content/main', array(
					'latest_content' => $latest_content,
					'content' => $post,
				)
			);
		} else {
			$this->template->content = View::factory('content/main', array(
					'content' => array(
						'type' => Content::TYPE_UNKNOWN,
						'description' => 'Content not found',
					),
				)
			);
		}
	}
}

 

Define the content controller (~/modules/content/classes/controller/content.php):

<?php
class Controller_Content extends Controller_Base_Content { }
?>

 

Store some configuration values for the module (~/modules/content/config/content.php):

 array(
		'name' => 'default',
		'style' => array(
			'media/css/3-column-px.css' => 'screen',
			'media/css/screen.css' => 'screen, projection',
			'media/css/print.css' => 'print',
			'template/default/css/style.css' => 'screen',
		),
		'script' => array(
			'http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js',
		),
	),
);

 

 

……………………………………………………………

 

Great way to integrate SwiftMailer and Kohana 3

Just found this post:

http://www.flynsarmy.com/2010/06/integrating-swift-mailer-into-kohana-3/

by Flynsarmy

showing the simplest way to integrate SwiftMailer and Kohana 3

Create the following files/folders:
/modules/swiftmailer
/modules/swiftmailer/init.php
/modules/swiftmailer/classes

Inside /modules/swiftmailer/classes/ drop the official latest build of Swift Mailer.

Enter the following into init.php.

<?php
require Kohana::find_file('classes', 'Swift-4.0.6/lib/swift_required');

There. Wasn’t that easy? Remember to enable the module by adding it to your bootstrap.php file!

php:// function to clean string for SEO usage

If you need a good function to clean strings to use them as URLs for SEO purposes, here’s a suggestion:

function chunk_special_chars($string) {
  $normalizeChars = array(
    'Š'=>'S', 'š'=>'s', 'Ð'=>'Dj','Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A',
    'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E', 'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I',
    'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U', 'Ú'=>'U',
    'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss','à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a',
    'å'=>'a', 'æ'=>'a', 'ç'=>'c', 'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i',
    'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o', 'ö'=>'o', 'ø'=>'o', 'ù'=>'u',
    'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y', 'ƒ'=>'f'
  );
  $string = strtr($string, $normalizeChars);
  $string = str_replace('&', '-and-', $string);
  $string = trim(preg_replace('/[^wd_ -]/si', '', $string));//remove all illegal chars
  $string = str_replace(' ', '-', $string);
  $clean = iconv('UTF-8', 'ASCII//TRANSLIT', $string);
  $clean = preg_replace("/[^a-zA-Z0-9/_| -]/", '_', $clean);
  $clean = strtolower(trim($clean, '-'));
  $clean = preg_replace("/[/_| -]+/", '_', $clean);

  return $clean;
} //function

thanks to: sales at mk2solutions dot com for posting their solution @http://us2.php.net/strtr notes

Kohana v3.03 reset

Download Kohana v3.0.3

Upload files to your server

Fix these paths inside index.php:

$application = '../application';
$modules = '../modules';
$system = '../system';

Try accessing to make sure you installed correctly:

http://kohanav3.portnumber53.com/

Some tweaks:

Inside application/bootstrap.php:

date_default_timezone_set('America/Los_Angeles');
kohana::init(array(
 'base_url' => '/',
 'index_file' => '',
));

Now create: application/classes/controller/layout.php

Now extend the previous controller: application/classes/controller/website.php

And create a controller to handle content: application/classes/controller/content.php

Great way to parse HTML content using PHP

Today I started improving a newsletter system in the company I work for. One of the things I wanted to change is to have images embedded in the email message.

The website uses CodeIgniter (http://www.codeigniter.com); for email handling I chose Swift mailer (http://swiftmailer.org/). Then for HTML parsing to replace all the relative image paths and encode/embedded the images in the message I found this parser: SimpleHTMLDOM (http://simplehtmldom.sourceforge.net/).

Really simple to use and now I’m working on the rest of the stuff… managing templates for newsletter, handling subscription etc etc.

I’m going to add some sample code later. Drop me a line if I take too long.

  • IGlr