While building admin/CMS or just a form on your site you might need to build a dropdown (select) list with values read from database. It is very elegant to do this with Laravel’s Eloquent. (For the sake of this post let’s assume that you want to read values from the database and not from some array stored in a class or somewhere else.)
Let’s suppose the database table is called “countries” and is already populated (You can get one here). It contains, you guessed it, a list of country names, which you would like to display in a HTML dropbox list.
First, create a model named “Country.php” (you can use artisan, excellent Laravel 4 generators or create it manually. Keep in mind that the model name is singular (Country) and the database table is plural (Countries).
In your controller add:
$country_options = Country::lists('short_name', 'id');
Simple isn’t it? This will return an array of values like “[1] => Afghanistan [2] => Aland Islands”… (We are assuming that database field name containing country names is “short_name”).
Note: Personally I like Eloquent but in case you do not want to use Eloquent or/and do not want to have an empty Country.php model lying there just so you can populate drop-down then you can use Laravel’s Fluent Database Query Builder:
$country_options = DB::table('countries')->orderBy('short_name', 'asc')->lists('short_name','id');
Ok, now let’s send this to view with ->with
:
return View::make('admin/customers/create')->with('country_options',$country_options);
In above case I am sending $country_options
to admin view that is used to create customers.
In the view you display it like this:
{{ Form::select('country', $country_options , Input::old('country')) }}
That is all it takes to have a functioning drop-down select box. As you can see we are using Laravel Blade template engine and Form class. With Input::old('country'))
we re-populate it with old values (for example after the form is submitted and there are some errors)
How to combine more fields with concat
In another case (for “customers”) I needed to combine two table fields into one and then populate the drop down with it: customers “first_name” + “last_name” should be “first_name last_name”. You can do this by combining Fluent Query Builder with Eloquent:
$customer_options = Customer::select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');
As you can see we are mixing Eloquent and DB:raw method.
Note: If you only want to use Laravel’s Database Query Builder then you can do this:
$customer_options = DB::table('customers')->select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');
How to add default option to dropdown list
Sometimes we want to have some default value that gives us some instructions what to do (“Please select a country,…”) with the dropdown or maybe even some default “non-value” (in case user doesn’t want to select anything). The easiest way to do this is to add array('' => 'Select One') +
so our code looks like this (few examples with the code in this post):
$country_options = array('' => 'Please Select Your Country') + Country::lists('short_name', 'id');
//or
$customer_options = array('' => 'Select Customer') + Customer::select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');
//and so on..
Keep in mind that you will have to add some validation (jQuery, Laravel’s own validation etc) in case user leaves the default option (in example above we leave the value as empty but you can set it to anything you want).
I really love Laravel 4, it makes developing so much fun and simple.