Hehe, masih dengan Kohana 3 dan Jelly ORM.
Ceritanya kita mau bikin permalink seperti pada postingan sebelumnya, tapi karena sekarang pake Kohana dan Jelly sebagai ORM-nya, kenapa ga kita coba implement aja?
Di Jelly, sebenernya udah ada fasilitas buat ngebikin slug itu, otomatis juga, cuman ga unique. Liat code berikut:
class Model_Category extend Jelly_Model
{
public static function initialize(Jelly_Meta $meta)
{
/**
* defaultnya sih categories, tapi kalo kita punya table berbeda,
* pake method table() buat definisi nama table
*/
$meta->table('kategori')
->fields(array(
'id' => new Field_Primary,
'name' => new Field_String,
'slug' => new Field_Slug,
));
}
public function save($key = null)
{
if ( ! $this->loaded() )
$this->slug = $this->name;
return parent::save($key);
}
}
Kita sudah selesai membuat class Model_Category, sekarang kita coba bikin category-nya. Oh ya.. udah kebayang belum tablenya seperti apa? Kalo belum, table kategori itu seperti ini (berdasarkan model).
id | name | slug -------------------------------------- 1 | contoh kategori | contoh-kategori
Ok, table sama model udah siap, sekarang bikin :)
$category = Jelly::factory('category');
$category->name = 'Contoh kategori ke-2';
$category->save();
Loh koq slug sama name sama? hehe iya, tapi secara otomatis, Jelly akan merubahnya menjadi slug, coba kita liat lebih jauh ke class Jelly_Field_Slug, pada method set() Jelly akan merubahnya menjadi contoh-kategori-2.
Ok ok, emang gampang, sekarang bagaimana dengan slug yg unique itu?
Hampir semua class yang ada pada Kohana bisa kita extends, termasuk Jelly!. Kita bisa override semua method di class yang ada.
Ok.. itu gw juga dah tau, gmn cara ngebikin unique?
Er... ok, gini, kita bikin 3 buah file buat extends Jelly. yang pertama class Field_Slug, kedua class Jelly_Meta dan yang terakhir Jelly.
APPPATH
|- classes
|- field
| - slug.php // class Field_Slug
|
|- jelly
| - meta.php // class Jelly_Meta
|
- jelly.php // class Jelly
Pada class Field_Slug, isinya seperti berikut:
<?php defined('SYSPATH') or die('No direct script access.');
class Field_Slug extends Jelly_Field_Slug
{
public function save($model, $value, $loaded)
{
return $this->set_slug($value);
}
public function set($value)
{
if ($value === NULL OR ($this->null AND empty($value)))
return NULL;
return $value;
}
private function set_slug($value)
{
$temp = $this->_slug($value);
$model = Jelly::select($this->model)
->where(':slug_key', 'REGEXP', "^{$temp}(-[[:digit:]])?")
->execute();
if ($model->count() > 0)
{
$number = array();
$found = false;
foreach ($model as $m)
{
if ($m->{$this->column} == $temp)
$found = true;
if (preg_match('/-(\d+)$/i', $m->{$this->column}, $match))
$number[] = $match[1];
}
if (sizeof($number) > 0)
$value = "{$value}-".(max($number) + 1);
elseif ($found)
$value = "{$value} 2";
}
return $this->_slug($value);
}
private function _slug($value)
{
$value = preg_replace('/[^a-z0-9-\/]/', '-', strtolower($value));
$value = preg_replace('/-{2,}/', '-', $value);
$value = trim($value, '-');
return $value;
}
}
Whuihh.. panjang juga ^^.. tapi.. lanjuttt... skr ke class Jelly_Meta.
<?php defined('SYSPATH') or die('No direct script access.');
class Jelly_Meta extends Jelly_Meta_Core
{
protected $slug_key = 'slug';
public function slug_key($value = NULL)
{
if (func_num_args() !== 0)
return $this->set('slug_key', $value);
return $this->slug_key;
}
}
Dan yang terakhir, kita override method meta_alias di dengan cara extends class Jelly_Core.
<?php defined('SYSPATH') or die('No direct script access.');
abstract class Jelly extends Jelly_Core
{
public static function meta_alias($meta, $field, $value = NULL)
{
if (is_string($meta) OR $meta instanceof Jelly_Model)
$meta = Jelly::meta($meta);
if (substr($field, 0, 1) !== ':')
{
list($model, $field) = explode(':', $field);
$field = ':'.$field;
if (FALSE == ($meta = Jelly::meta($model)))
{
throw new Kohana_Exception('Meta data for :model was not found while trying to resolve :field', array(
':model' => $model,
':field' => $field));
}
}
switch ($field)
{
case ':primary_key':
$field = $meta->primary_key();
break;
case ':name_key':
$field = $meta->name_key();
break;
case ':foreign_key':
$field = $meta->foreign_key();
break;
case ':unique_key':
$field = Jelly::builder($meta->model())->unique_key($value);
break;
case ':slug_key':
$field = $meta->slug_key();
break;
default:
throw new Kohana_Exception('Unknown meta alias :field', array(
':field' => $field));
}
return $field;
}
}
Nah sekarang penjelasan tiap2 perubahan di class itu. Kita mulai dengan Jelly. Perubahannya sedikit, cuman nambahin meta alias :slug_key (lihat bagian switch) yg akan kita butuhin nanti.
Pada class Jelly_Meta, kita menambahna definisi slug_key, dan method untuk merubah field slug_key (default kita set ke slug).
Dan yang drastis berubah adalah class Field_Slug, disini kita baru implementasi apa yang kita bahas di postingan sebelumnya, yaitu slug yang unique, cuman disini gw ga begitu yakin dengan kebersihan code nya.. hehehe...
Lihat disana ada ->where(':slug_key', ...). ':slug_key' ini ga ada, kita tadi tambahkan di class Jelly_Meta sama di class Jelly. Meta alias ini kita tambah biar nanti kepake sama table yang laen, yang field slug nya berbeda. Misal:
<?php defined('SYSPATH') or die('No direct script access.');
class Model_Post extends Jelly_Model
{
public static function initialize(Jelly_Meta $meta)
{
$meta->slug_key('permalink')
->name_key('title')
->fields(array(
'id' => new Field_Primary(),
'title' => new Field_String(),
'permalink' => new Field_Slug(),
));
}
public function save($key = NULL)
{
if (! $this->loaded())
{
$this->permalink = $this->title;
}
return parent::save($key);
}
}
Wahhh panjang banget.. pusing :( hehehe.. iya panjang banget soalnya, tapi ntar cara pakenya sama, sederhana, seperti tadi contoh di atas pas kita bikin kategori.
- Posted about a year ago
- Updated Tue, 23 Nov 2010
Latest Comments