Urls usando ’slug’
Posted: December 18th, 2007 | Author: andre | Filed under: CakePHP | No Comments »Vo mostrar aqui como utilizar urls em estilo slug como o wordpress. As razões de utilizar esse tipo de recurso é simples, as urls ficam mais apresentáeis e intuitivas e tornando-se mais atraentes. O precesso de adaptação é bem simples, utilizando mais um field ’slug’ na tabela do banco e usando esse campo ao invés do id para procura.
CREATE TABLE contents ( id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,images_id INTEGER UNSIGNED NOT NULL,title VARCHAR(45) NULL, slug VARCHAR(100) NULL, text TEXT NULL, created DATETIME NULL, updated DATETIME NULL, PRIMARY KEY(id), UNIQUE INDEX contents_index1129(slug) );
Com a table já pronta, podemos editar o controler. Para isso vamos mudar a function “view” do contents_controller.php.
A seguir o code original criado a partir do bake.php:
function view($id = null) { if (!$id) { $this->Session->setFlash('Invalid id for Content.'); $this->redirect('/contents/index'); } $this->set('content', $this->Content->read(null, $id)); }
Agora a modificação, e então ocorre a mágica:
function view($slug = null) { if (!$slug) { $this->Session->setFlash('Invalid id for Content.'); $this->redirect('/contents/index'); } $this->set('content', $this->Content->findBySlug(null, $slug)); }
Com o método ‘findBy’ vc escolhe qual campo vc deseja usar para a procura, no caso nosso campo ’slug’ da tabela.
Então para completar a mudança só é preciso agora alterar as views de modo que nos links seja indicado não a ID e sim o Slug da página requisitada:
... <td class="actions"> <?php echo $html->link('View','/contents/view/' . $contents['Content']['slug'])?> <?php echo $html->link('Edit','/contents/edit/' . $contents['Content']['slug'])?> <?php echo $html->link('Delete','/contents/delete/' . $contents['Content']['slug'], null, 'Are you sure you want to delete id ' . $contents['Content']['slug'])?> </td> ...
Agora uma última implementação, reparam que usamos na tabela a campo ’slug’ como UNIQUE, obviamente é necessário que essa entrada seja única no banco de dados para que duas páginas não tenham o mesmo ’slug’ perdendo assim a funcionalidade que mostramos aqui. Só é necessário alterar a function ‘add’ no próprio controller:
function add() { if (empty($this->data)) { $this->render(); } else { $this->cleanUpFields(); /*aqui preencho o campo slug com o title + a data pra formar uma entrada unica */ $this->data['Content']['slug'] = $this->Common->title_slug($this->data['Content']['title'].'-'.date('Y-m-d H:i:s')); if ($this->Content->save($this->data)) { $this->Session->setFlash('The Content has been saved'); $this->redirect('/contents/index'); } else { $this->Session->setFlash('Please correct errors below.'); } } }
Repare que foi utilizado um component ‘Common’ cujo codigo é disponibilizado a seguir, basta criar o arquivo /controllers/components/Common.php com ele e chama-lo usando “var $components = array(‘Common’);”.
class CommonComponent extends Object{ function title_slug( $title ) { $slug = $title; $bad = array( 'Š','Ž','š','ž','Ÿ','À','Á','Â','Ã','Ä','Å','Ç','È','É','Ê','Ë','Ì','Í','Î','Ï','Ñ', 'Ò','Ó','Ô','Õ','Ö','Ø','Ù','Ú','Û','Ü','Ý','à','á','â','ã','ä','å','ç','è','é','ê', 'ë','ì','í','î','ï','ñ','ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','ÿ', 'Þ','þ','Ð','ð','ß','Œ','œ','Æ','æ','µ', '"',"'",'“','"',"n","r",'_'); $good = array( 'S','Z','s','z','Y','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','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','y', 'TH','th','DH','dh','ss','OE','oe','AE','ae','u', '','','','','','','-'); // replace strange characters with alphanumeric equivalents $slug = str_replace( $bad, $good, $slug ); $slug = trim($slug); // remove any duplicate whitespace, and ensure all characters are alphanumeric $bad_reg = array('/s+/','/[^A-Za-z0-9-]/'); $good_reg = array('-',''); $slug = preg_replace($bad_reg, $good_reg, $slug); // and lowercase $slug = strtolower($slug); return $slug; } }