Skip navigation

Monthly Archives: November 2011


Salah satu aplikasi yang sedang saya kembangkan menggunakan username vanity URL. Maksudnya adalah pada setiap pengguna akan mempunyai sebuah link yakni username pengguna yang ditempelkan pada domain. Contohnya adalah seperti twitter. URL twitter saya adalah http://www.twitter.com/petrabarus. Pada URL tersebut username saya petrabarus ditambahkan pada domain twitter.com. Sekarang kita ingin membuat sebuah aplikasi yang dapat mengakses user saya petrabarus dengan alamat http://aplikasi/petrabarus.

Sebelum Yii 1.1.8, implementasi ini agak sedikit kompleks (saya tidak tertarik untuk membahasnya). Tapi sejak adanya kelas CBaseUrlRule, ini jadi lebih mudah.

Pertama-tama, misalnya kita mempunyai kelas model User yang digenerate dari Gii. Saya yakin hampir semua aplikasi Yii memiliki kelas seperti di bawah.

/*
* The followings are the available columns in table 'Users':
* @property integer $id
* @property string $username
* @property string $email
*/
class User extends CActiveRecord {
}

Dengan adanya ActiveRecord class bawaan Yii, kita dapat dengan mudah mengkueri user berdasarkan usernamenya

$username = 'petrabarus';
User::model()->find('username = :username', array(':username' => $username));

Kemudian kita mempunyai sebuah controller untuk melihat user tersebut

class UserController extends CController {
	public function actionView(){
		$username = $_GET['username'];
		$model = User::model()->find('username = :username', array(':username' => $username));
		$this->render('view', array('model' => $model));
	}
}

Untuk mengakses URLnya biasanya yang kita lakukan adalah mengakses http://aplikasi/user?username=petrabarus.

Sekarang kita tinggal membuat sebuah URL Rule seperti di bawah

class UserUrlRule extends CBaseUrlRule {

	public $connectionID = 'db';

	public function createUrl($manager, $route, $params, $ampersand) {
		if ($route === 'user/view' && isset($params['username'])) {
			$newroute = $params['username'];
			unset($params['username']);
			if (count($params) > 0) {
				$newroute.= '?' . http_build_query($params);
			}
			return $newroute;
		}
		return false;
	}

	public function parseUrl($manager, $request, $pathInfo, $rawPathInfo) {
		if (preg_match('/[a-zA-Z0-9\.]+/', $pathInfo, $matches)) {
			$username = $matches[0];
			$exists = User::model()->exists('username = :username', array(':username' => $username));
			if ($exists) {
				$_GET['username'] = $username;
				return 'user/view';
			} else
				return false;
		}
		return false;
	}

}

Method parseUrl dibutuhkan untuk memparsing url yang diakses melalui address bar browser. Sementara itu method createUrl adalah untuk membentuk URL yang kita inginkan. Method createUrl ini nantinya akan digunakan oleh method createUrl milik Controller. Pada method parseUrl itu saya memfilter URL tersebut dengan regex /[a-zA-Z0-9\.]+/ yang merupakan pattern rule dari username pada aplikasi saya. Kemudian jika ada yang mirip maka string pada URL tersebut akan saya periksa apakah ada user yang memiliki nama yang sama. Jika ada maka request dialihkan ke Controller user/view.

Perlu diperhatikan, agar username tidak bentrok dengan URL-URL yang dimiliki oleh Controller ada baiknya kita mempunyai daftar username yang diblacklist, yang diantaranya adalah nama-nama Controller seperti misalnya login, logout, signin, signout, register, dan lain-lain.

Lalu kita tambahkan ke rule di konfigurasi.

'urlManager' => array(
	    'urlFormat' => 'path',
	    'showScriptName' => false,
	    'rules' => array(
		array(
		    'class' => 'application.components.UserUrlRule',
		    'connectionID' => 'db',
		),
		'<controller:\w+>/<id:\d+>' => '<controller>/view',
		'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
		'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
	    ),
	),

Dan sekarang kita bisa mengakses halaman user dari http://aplikasi/petrabarus. Untuk mendapatkan URL ini pada Controller, kita cukup memanggil

$this->createUrl('user/view', array('username' => 'petrabarus'));

Saya membutuhkan sebuah fungsi untuk menyisipkan parameter query pada sebuah parameter di kode Javascript saya.

Misalnya, untuk URL

http://www.example.com/home?foo1=bar1#anchor

saya ingin menyisipkan parameter “foo2” dengan nilai “bar2”, sehingga menjadi

 http://www.example.com/home?foo1=bar1&foo2=bar2#anchor
 

Lihat bahwa penyisipannya cukup rapi dengan menempatkan variabel tersebut pada bagian parameter dan masih menangani anchor “#anchor”.

Setelah mencari di StackOverflow (When in doubt, ask StackOverflow), saya mendapatkan kodenya.

function addParameter(url, parameterName, parameterValue){

	replaceDuplicates = true;
	
	if(url.indexOf('#') > 0){
		var cl = url.indexOf('#');
		urlhash = url.substring(url.indexOf('#'),url.length);
	} else {
		urlhash = '';
		cl = url.length;
	}
	
	sourceUrl = url.substring(0,cl);
	
	
	
	var urlParts = sourceUrl.split("?");
	var newQueryString = "";
	
	if (urlParts.length > 1)
	{
		var parameters = urlParts[1].split("&");
		for (var i=0; (i < parameters.length); i++)
		{
			var parameterParts = parameters[i].split("=");
			if (!(replaceDuplicates && parameterParts[0] == parameterName))
			{
				if (newQueryString == "")
					newQueryString = "?";
				else
					newQueryString += "&";
				newQueryString += parameterParts[0] + "=" + parameterParts[1];
			}
		}
	}
	if (newQueryString == "")
		newQueryString = "?";
	else
		newQueryString += "&";
	newQueryString += parameterName + "=" + parameterValue;

	return urlParts[0] + newQueryString + urlhash;
}

Cara menggunakannya adalah

url = addParameter("http://www.example.com/home?foo1=bar1#anchor", "foo2", "bar2");

Kodenya di StackOverflow dapat dilihat di sini.

 

%d blogger menyukai ini: