I'm trying to populate a drop down menu with database results in Laravel 4. I'm extremely new to Laravel. This is actually my first site and I'm learning as I go. So, please tell me if I'm using the wrong terminology or not enough information.
I've got a database of company info and I need users to be able to choose a company from a dropdown. Or if the company isn't in the database to add it.
For the select menu, it needs to go like this:
[company name result]
And I'm using this code in my controller:
$companies = RecordCompany::get();
$company_selector = array();
foreach($companies as $company) {
$company_selector[$company->id] = $company->id;
$company_selector[$company->company_name] = $company->company_name;
}
return View::make('admin.record_new', array('company_selector' => $company_selector));
And this is what I've got in my view:
#if(count($client_selector)>0)
{{ Form::select('company_id', $company_selector, array_values($company_selector)[0]) }}
#endif
Disclaimer: I found this code online.
First, I don't understand how it will populate the value and option text without my telling it where to put the data.
Second, the error that's coming back is unexpected . When I take out the [0] in the form code, it tells me that $company_selector is undefined.
What am I doing wrong here?
In order to populate a dropdown menu with all the records from the RecordCompany model, you can do the following, in your view:
{{ Form::select('company_id', RecordCompany::lists('company_name', 'id')) }}
Note: In Laravel 5, the method lists has been deprecated. Use
pluck instead.
Explanation of the code:
The Form::select methods creates a HTML select tag.
company_id is the name of the select tag.
The second parameter is the options for the select tag. The lists method in any model (RecordCompany in this case) generates an associative array containing the parameters passed to that method (id and company_name in this case) of all the records in the model's database table.
If you want, you can also call the lists method from the controller and then pass the value to the view, like following:
In Controller
$company_lists = RecordCompany::lists('company_name', 'id');
return View::make('admin.record_new', array('company_lists' => $company_lists));
In View
{{ Form::select('company_id', $company_lists) }}
You can view the Laravel 4 documentation for generating a drop down list here: http://laravel.com/docs/html#drop-down-lists
I'm severelly against using DB calls in views. And here is why:
It ain't made for that!.
Period.
If I where you (note the if clause) I'd like better to fulfill a regular array, being the company->id the array key and any other information you may wanna for that especific key as a value. On my blade code, I'd made that way:
{{ Form::select('company_id', $companies) }}
Where "companies" would be a array passed as argument to the view by the controller.
Views aren't made to make DB consults. They are made to display data. JUST IT!
That being said:
The first argument on the Form::select is the selector's name. The one you get on the Input::get.
The second argument is the list for fulfill the select attribute (we already talked about it up there!)
And the third, non less important, is where you say which one comes selected on loading page (used for editions). You have to reference the identifier (the company id, in that case). It's optional, for obvious reasons.
If I didn't made myself clear, please ask down here! =D
For Laravel 5, you can code like this :-
Controller Code
$company_lists = RecordCompany::pluck('company_name', 'id');
return View::make('admin.record_new', $company_lists);
View Code
{{ Form::select('company_id', $company_lists) }}
Related
I have no issues loading a unique record from my DB utilizing F3's ORM. However, when I want to retrieve multiple records for display or processing, the load method will still only fetch the first it finds.
I've found this on the docs:
By default, a data mapper's load() method retrieves only the first
record that matches the specified criteria. If you have more than one
that meets the same condition as the first record loaded, you can use
the skip() method for navigation
However the docs then continue only to show how to manipulate multiple records with built in find method, which returns an object filled with references to database entries.
I prefer not to loop through multiple records every time, I think there must be something I'm missing, how does one do this with fat free? In the docs it even references code where you can just do the following after a simply DB call, but I've yet to see how to do that with provided methods:
<repeat group="{{ #result }}" value="{{ #item }}">
<span>{{ #item.brandName }}</span>
</repeat>
What is the proper way to obtain a batch of records? For an example, please see below:
$productList = $products->load(array('created_on >= ?', $date->timestamp)); //Load most recently created products
or
$productList = $products->find(array('created_on >= ?',$date->timestamp),array('order'=>'created_on'));
In the example above, the date is utilizing Carbon, assume that is a proper timestamp.
I don't think there is a proper way to retrieve a bunch of records. The SQL mapper acts as a cursor. The best way to see how it works is with the load method: the mapper will retrieve all matching records and set its focus on the first one. You can do what you want with it and then call next to move on to the next one:
$products->load(array('created_on >= ?', $date->timestamp));
while (!$products->dry() ) {
// Do something with the record
$products->next();
}
The find method will return an array of records (actually they are also cursors, but each has only one record so you can treat them just as objects which are mapped to the records). Here, you will need to assign the result to a new variable like you did in your example:
$productList = $products->find(array('created_on >= ?',$date->timestamp),array('order'=>'created_on'));
// You can loop over the array to get some info or update the records:
foreach ($productList as $product) {
// Do something with the record
}
Or you can directly use the $productList variable in the template:
<repeat group="{{ #productList }}" value="{{ #item }}">
<span>{{ #item.brandName }}</span>
</repeat>
I have model User and inside there is a field named title.
Now I want to define all possible titles. For example an array of
['0' => 'Mr.', '1' => 'Ms.']
What is the correct way to define these.
My idea is to create the public function titles() { return ['0' => 'Mr.', '1' => 'Ms.']; inside the User.php model and call for the array as $user->titles() whenever I need it. However this makes me twitch a bit because I'm calling the function on the model instance.
I really don't think creating a relation here is needed as there aren't more than ten possible titles.
Is there a better/right way to do these kind of things. I'm not that new to Laravel but I'm self thought so I'm trying to check my ways of doing stuff here.
I need to get into these oop basics a bit so any pointers here are helpfull.
Thanks in advance.
One way to do this is to keep titles in config file, like:
'titles' => [
1 => 'Mr.',
2 => 'Mrs.'
....
],
Benefits are:
you can edit this info at any time (keeping data hardcoded into model class is a bad practice)
you can use this list as is for select list building
you can keep data as TINYINT by keeping title IDs, sometimes it's a benefit
To build select list, do something like this:
{!! Form::select('titles', config('custom_config.titles'), 1) !!}
If you want dynamic select box write this code
$titles = User::lists('title', 'id'); // controller
{!! Form::select('title', $titles, null, ['class' => 'form-control']) !!} // view
You can use config files as #Alexey Mezenin suggested, but in this cases I prefer to use the database to store that kind of options (I mean in a different table, not in same users table), so I can add or delete options without touching the code and use the same form template/partial across different pages or projects if needed.
If you just need to retrieve the array it would be as easy as make a query in your controller and return it, but if you need it for form options I suggest you to use something like a form builder helper in which you get the form options from database and build your form using laravelcollective package, then you can pass the helper object to your view to show your fields and show whatever info you need.
I keep getting this error:
ErrorException in 939c885abda79cfdae4288b828415df7 line 38:
Trying to get property of non-object
My Controller looks like this:
$episodes = Episode::orderBy('id', 'desc')->paginate(5);
$channels = Channel::lists('channel_name', 'id')->all();
return view('app.admin.episodes', compact('episodes', 'channels'));
And the view:
{!! Form::Label('Select Channel') !!}
<select>
#foreach($channels as $channel)
<option value="{{$channel->channel_name}}">{{$channel->id}}</option>
#endforeach
</select>
I am so clueless as to why this is so. My question is, is it not possible to pass data from more than one table to a view like i did in my code snippet in Laravel? I want to believe there MUST be a way to go about that in Laravel 5.1 but how???? Checked the documentations, seen many blog posts all leading me nowhere. Can anybody just save me this pain..... Thanks
To access the elements in the array, use array notation: $channel['channelname'] and $channel['id'] By doing this: $channel->channel_name, you are trying to access an objects property.
Starting Laravel 5.1, the lists method now returns a collection rather than an array. Calling all() convert it to an array. Source: http://laravel.com/docs/5.1/upgrade
Seeing that you are using the Form Builder though, you can simply use the select method instead and let it handle it for you. Then, you can simplify your code to this:
{!! Form::label('Select Channel') !!}
{!! Form::select('channel', $channels) !!}
Change 'channel' to whatever input name you are using.
The lists method returns an associative array, in which the values come from the column passed as the first parameter (channel_name) and the item keys from the column passed as the second parameter (id). So in your case, you're getting an array that has the following structure for its items:
['id' => 'channel_name']
Which means that when iterating with #foreach, you need to use the key of the array as the id and the value as the channel name. Also you've switched out the value and text displayed, so the value should be the ID not the name, unless you want a dropdown that let's you select ID's:
<select>
#foreach($channels as $id => $name)
<option value="{{ $id }}">{{ $name }}</option>
#endforeach
</select>
You can read more about how the lists method works, in the "Retrieving a list of column values" subsection form the Queries: Retrieving Results Laravel Documentation.
I am making a select list of my users, but my user are stored in my database with a lastname and firstname. And all the documentation on lists use only one column item from te database. How do I get both these names in my list?
Controller
public function make() {
$users = User::lists('lastname','id');
return View::make('admin.awardAchievement')->with('users', $users);
}
View
{{ Form::select('user', $users , Input::old('user')) }}
This wil only print out the lastname of my users, but I want the list to show the firstname and lastname.. Can someone please help?
You can do this by using a custom DB expression and concatenate lastname + id. This because the Form helper only likes 1 column for the text (option text) and 1 column for the id (option value attribute).
$users = User::select(DB::raw('CONCAT(lastname, id) AS userselect, id'))->lists('userselect', 'id');
I find this the way to go, except you have to keep in mind that CONCAT can behave differently on different DBMS's or this function could not even exist. If you do care about this, I would just loop through your users list and manually concatenate with standard PHP script.
Another option is to just adjust the Form helper to support your needs. Though I would not recommend doing this if you want to keep your code rapidly upgradable.
EDIT: Check first comment
You can add a setter to your model, so something like:
public function getFullNameAttribute()
{
return $this->attributes['firstname'] . ' ' . $this->attributes['lastname'];
}
and then you can just do
$users = User::lists('fullname','id');
I wish to make a select box of city names for a form. I have been able to create and pass to my view an object $city whose values I can correctly list on my view if I simply display them outside of a form. The two properties of $city that are needed for the select box are: $city->id and $city->name.
My attempts to do this using Blade are failing. The issue boils down to: how do I nest #foreach inside of the Blade Form::select statement? For example, without the #foreach, just plunking in a couple of cities, this works perfectly, including a choice of blank, and a default of Albuquerque:
{{ Form::open() }}
{{ Form::Label('city_bldg_id','City:') }}
{{ Form::select('city_bldg_id', array(
'',
'2'=>'Albuquerque',
'11'=>'Bernalillo'
),'2') }}
{{ Form::close() }}
In order to populate the select box with all of the values in $city, it would seem that I need to use #foreach inside of the Form::select array. Is this possible to do? If so, how? All of my attempts yield syntax errors. Or, must $city be an array and not an object?
I am so close I can taste it, but I can't figure out the last step. Any suggestions for the appropriate code would be greatly appreciated. Thanks!
I generally prefer creating the select data before going to the view. It's easier to read if it's just
{{ Form::select('city_bldg_id', $cities, '2' }}
(Side note: not sure if you need to enclose the 2 in quotes. Probably not.)
That way, you can do foreaches all you want in order to create the array, and you can do it in pure PHP instead of in Blade.
One simply way to create the array if you're getting the data from an Eloquent model, e.g. City, is the lists() method:
$cities = City::lists('name', 'id');
If you need to filter out specific cities, you just do it the normal way:
$cities = City::where('somefield', '=', 'value')-> etc... ->lists('name', 'id');
(I hope I'm not assuming too much about what you know already. If this seems too beginnerish and it doesn't help you, I apologise.)