Create object in JavaScript using named parameters

The following code should look familiar, we’re creating an object and assigning a property.

function Person(id) {
	var self = this;
	self.id = id;
}

var instance = new Person(1);

One challenge with this approach is that as you add properties remembering their order can become a mental task.

function Person(id, firstName, lastName, phoneNumber) {
	var self = this;
	self.id = id;
	self.firstName = firstName;
	self.lastName = lastName;
	self.phoneNumber = phoneNumber;
}

var instance = new Person(1, 'Bill', 'Gates', '212-555-1234');

An alternate approach to consider is to use jQuery’s extend function (or Underscore, AngularJS, etc) which enables passing named parameters.

function Person(data) {
	var self = this;
	$.extend(self, data);
}

var instance = new Person({
	id: 1,
	firstName: 'Bill',
	lastName: 'Gates',
	phoneNumber: '212-555-1234'
});

A nice by-product of this approach is that it makes it simple to serialize/de-serialize the object, for example to store it to Local Storage.

var jsonString = JSON.stringify(instance);
// write to storage
// ...
// read from storage
var instance = new Person(JSON.parse(jsonString));

Logging errors in Laravel

Laravel comes with a really helpful Log::error() function to write messages to the log file. Here’s how you can use it to track PHP and JavaScript errors along with useful contextual information to help troubleshoot problems.

The Log::error() function accepts a second optional parameter allowing you to specify additional info. To make setting this easier create a logError() function in a Utils class.

public static function logError($error, $code = '', $context = 'PHP')
{
	$count = Session::get('error_count', 0);
	Session::put('error_count', ++$count);

	$data = [
		'context' => $context,
		'user_id' => Auth::check() ? Auth::user()->id : 0,
		'user_name' => Auth::check() ? Auth::user()->getDisplayName() : '',
		'url' => Request::url(),
		'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '',
		'ip' => Request::getClientIp(),
		'count' => $count,
		'code' => $code
	];

	Log::error($error, $data);
}

Most of the code should be self explanatory. getDisplayName() is a function I add to the User class (as well as other classes) where there is logic involved in determining the name. In this case it may be the user’s full name or email address.

To configure Laravel to use this function by default change the App::error() function in app/start/global.php to the following.

App::error(function(Exception $exception, $code)
{
	Utils::logError($exception, $code);
});

To catch all JavaScript errors enable accessing the Utils::logError() function by adding this to your routes.php file.

Route::get('/log_error', function() 
{
	return Utils::logError(Input::get('error'), '', 'JavaScript');
});

And finally, add the following to function to your master template file.

window.onerror = function(e) {
	try {
		$.ajax({
			type: 'GET',
			url: '{{ URL::to('log_error') }}',
			data: 'error='+e
		});     
	} catch(err) {}
	return false;
}

Wrapper for JavaScript console.log

One of the best ways to debug web applications is to use the console.log() function. The catch is while it works in Chrome as well as Firefox (with the Firebug plugin) it causes errors in IE.

Here’s my version of a very simple wrapper function which:
– Prevents errors in IE
– Supports the console functions I regularly use (log, info, warn and error)
– Allows using %s to substitute parameters. ie, log(“length is %s”, foo.length)

window.M5 = window.M5 || {};

$.each(["log","info","warn","error"], function() {
	var name = this;
	M5[name] = function () {
		if(!window.console) return; // prevents errors on IE
		console[name].apply(console, arguments);
	};        
});

// sample usage
M5.log("My test log message");

Note: this requires jQuery and uses the M5 namespace (which you may wish to change for your own application).