URL Username

Ada yang ngeimplementasikan ini gak?

Bisa disharing gak tekniknya di Yii?

ada yg mengimplementasikan ini pake Yii gak, maksudnya…

pertama harus buat controller bisa buka dengan username (karena pada umumnya kita kan buka page berdasarkan id…)

misalnya untuk buka profile saya punya Controller profile dan method view jadi


class ProfileController extends CController{

    public function actionView($p){

       //fungsi buat nampilin user

    }

}

otomatis link untuk mengaksesnya adalah


http://www.myweb.com/?r=profile/view&p=namaku

Langkah berikutnya adalah mengaktifkan urlmanager di config


'urlManager'=>array(

			'urlFormat'=>'path',

			'showScriptName'=>false,

			'rules'=>array(

				//mainPage Rules...

                                ...

				'<p:>'=>'/profile/view/',

                                ...

			),

		),

jika sudah diaktifkan maka dapat diakses dengan begini

http://www.myweb.com/namaku

Ini di saya sudah jalan, hanya saja ada beberapa hal yang menjadi catatan.

  1. Semua url sekarang akan menjadi SEO friendly dan tidak ada satupun yang menggunakan ?r=site/xxx lagi. Hati-hati bagi coding yang masih ada pakai coding $_GET[], karena tidak akan jalan. Saya masih belum menemukan cara untuk sebagian pakai url manager sebagian pakai url biasa.

  2. kalau sudah pakai sistem name, hati-hati dengan tabrakan nama. Misalnya kalau sudah diaktifkan urlmanager maka jika dulunya akses begini:

www.myweb.com/?r=search/

maka sekarang hasilnya adalah

www.myweb.com/search/

itu artinya kalau ada yang username nya "search" bakal tabrakan. Solusinya kalau tipenya controller, tambah rule baru supaya aksesnya jadi begini saja:

www.myweb.com/controller/search.

setidaknya lebih sedikit yang terjadi tabrakan nama.

Saya masih belajar jadi ini mungkin bukan solusi terbaik tetapi setidaknya yang sekarang inilah yang jalan…

Saya sebenernya awalnya pengennya cuman




http://domain/user/username



jadi tinggal ngasi route




            'rules' => array(

                '/user/<username:[a-zA-Z][a-zA-Z0-9_]+>' => '/profile/view',

                /* Rules yang lain */

            ),



tapi begitu development udah jalan cukup jauh, terus pindah ke rule yg mirip




                        'rules'=>array(

                                //mainPage Rules...

                                ...

                                '<p:>'=>'/profile/view/',

                                ...

                        ),



jadinya bener-bener berantakan dan harus tambal sana-sini,

sebenernya ada ide modifikasi komponen Applicationnya,

begitu abis dapet rule dari runController, kalau misalnya gagal (controller gak nemu) khan harusnya throw CHttpException 404,

langsung coba ngecek ke action ‘profile/view’, kalo gak nemu baru exceptionnya diterusin,

tapi kurang tau juga apa harus modifikasi kodenya, atau inherit komponennya terus ganti CWebApplicationnya pake komponen turunannya itu, atau ada semacam hooknya,

baru sebatas ide aja sih…

ga kebayang betapa ribetnya sistemnya fesbuk

sistem facebook saya curiga dia menggunakan SOA.

jadi mau tampil profile picture ada service tersendiri, tampil wall orang service sendiri, tampil friends orang service tersendiri. Nah khusus tampil profile ini dia bikin seo-friendly, sedangkan yang lainnya masih non-SEO-friendly.

karena setau ane dalam satu server, tidak bisa setengah pakai URL setengah pakai path(seo-friendly). Bener tidak yah? :huh:

kalo diliat2 facebook itu rada strict soal vanity urlnya,

khan kita cuman bisa ganti sekali doang :P

kalo di twitter kayaknya gara2 dia pake rails dari awal jadinya mudah, (kalo gak salah rails udah ada fitur ini deh CMIIW)

Setelah coba iseng-iseng, ini solusinya ngedit implementasi di error action. Jadi ceritanya saya make errorAction di controller baru error/index…

lumayan berhasil :D




class ErrorController extends Controller {

    /**

     *

     */

    public function actionIndex() {

        $error = Yii::app()->errorHandler->error;

        if ($error['code'] == 404) {

            if (($username = $this->checkUserURL()) !== NULL) {

                ob_clean();

                header("HTTP/1.0 200"); //biar gak balik jadi 404

                $_GET['username'] = $username;

                $this->forward('profile/view');

            } else {

                $this->render('404');

            }

        } else {

            $this->render('index', $error);

        }

    }


    private function checkUserURL() {

        $route = Yii::app()->getUrlManager()->parseUrl(Yii::app()->getRequest());

        $exists = User::model()->exists('username = :username', array(':username' => $route));

        return (($exists) ? $route : NULL);

    }

}



Oke, setelah dicoba ternyata cara di atas gak terlalu bersih juga. Soalnya dia itu selalu nulis error log setiap kali ngakses username. Jadinya ntar lognya bakal overbloated.

Sekarang gw nyoba2 cara kedua, yaitu nambah behaviour di CWebApplication

caranya tinggal bikin class "UsernameURLBehaviour" terus taro di protected/components

isinya




<?php


class UsernameURLBehaviour extends CBehavior {


    public function attach($owner) {

        // set the event callback

        $owner->attachEventHandler('onBeginRequest', array($this, 'beginRequest'));

    }


    /**

     * This method is attached to the 'onBeginRequest' event above.

     * */

    public function beginRequest(CEvent $event) {

        $route = Yii::app()->getUrlManager()->parseUrl(Yii::app()->getRequest());

        $exists = User::model()->exists('username = :username', array(':username' => $route));

        if ($exists && !is_array($event->sender->catchAllRequest)) {//if the route exists in username

            //catch all request to profile/view

            $event->sender->catchAllRequest = array(

                'profile/view',

                'username' => $route,

            );

        }

    }


}



terus di bagian protected/config/main.php




    'behaviors' => array(

        'onbeginRequest' => array(

            'class' => 'application.components.UsernameURLBehaviour',

        ),

    ),



selesai deh :D

Ane kurang ngerti tentang behavior. Itu attach behaviournya pada bagian mana yah?

Terus kalau pakai coding yang behavior itu, berarti request semua url dia akan query user atau hanya request url username saja?

Kalo untuk behaviour/event bisa dilihat di

http://www.yiiframework.com/doc/guide/1.1/en/basics.component

sama

http://www.yiiframework.com/wiki/44/behaviors-events/

jadi penjelasannya gini, kalo kita ngeliat di index.php (bootstrap) ada method run

nah di run() itu kalo kita lihat di CApplication




	public function run()

	{

		if($this->hasEventHandler('onBeginRequest'))

			$this->onBeginRequest(new CEvent($this));

		$this->processRequest();

		if($this->hasEventHandler('onEndRequest'))

			$this->onEndRequest(new CEvent($this));

	}



nah di situ dia ngeraise event ‘onBeginRequest’, disitu dia bakal nyari behaviour yang jadi event handlernya,

sekarang masalahnya adalah gimana cara nyantolin si event handler tersebut ke si application, itu dilakukan di config/main.php

di konfig itu, selain kita bisa nambahin componentsnya si application, kita juga bisa nambahin si behaviour, nanti itu diattachnya pas Yii::createWebApplication

gitu doang :D

lalu kenapa harus pake property catchAllRequest, kalo dilihat dari kode CWebApplication




	public function processRequest()

	{

		if(is_array($this->catchAllRequest) && isset($this->catchAllRequest[0]))

		{

			$route=$this->catchAllRequest[0];

			foreach(array_splice($this->catchAllRequest,1) as $name=>$value)

				$_GET[$name]=$value;

		}

		else

			$route=$this->getUrlManager()->parseUrl($this->getRequest());

		$this->runController($route);

	}



dia itu sebelum ngeresolve pake parseUrl, dia bakal ngecek catchAllRequest. Properti ini mostly digunain kalo kita mau bikin halaman "under maintenance"…

jadi sebenernya gak masalah juga sih kalo mau dipake pas resolve usernamenya

trus soal pencarian itu, dia emang ngecek ke database untuk setiap request url.

tapi kalo di databasenya si username nya itu diindex, harusnya overheadnya gak terlalu gede…

setelah meliat data dari fesbuk sepertinya search ke database dulu, contohnya

http://graph.facebook.com/1730693480 didapat


{

   "id": "1730693480",

   "name": "L Mukti Dwinata",

   "first_name": "L",

   "middle_name": "Mukti",

   "last_name": "Dwinata",

   "link": "http://www.facebook.com/TheBatax",

   "username": "TheBatax",

   "gender": "male",

   "locale": "en_US"

}

applikasi akan pertama kali search username di database baru kemudian return id yg digunakan utk identifikasi user

ntah yah,

gak yakin juga sih, apa pas nerima request HTTP, si facebook itu mesti ngecek dulu ke Graph APInya,

terus kalo ngesearch username abis itu dapet ID, terus disearch lagi IDnya, kayaknya dua kali kerja deh, soalnya username khan juga keindex,

what are things to be considered as an SEO?