Populating dropdown using Laravel Eloquent and DB - php

I'm on Laravel and Eloquent, and trying to populate a view's dropdown box with results of a select query.
In my controller:
public function uploadDocs($userid)
{
$doc_options = DB::select('select document.document_description from document where user_id = ?', array($userid));
return View::make('uploaddocs')->with('doc_options', $doc_options);
}
In my view:
<body>
{{ Form::select('doc_options_id', $doc_options) }}
</body>
I'm getting the following stack trace:
htmlentities() expects parameter 1 to be string, object given (View: /home/vagrant/code/eduview/app/views/uploaddocs.blade.php)
Any ideas? Thanks.

Try
$doc_options = DB::statement(DB::raw('select document.document_description from document where user_id = ?', array($userid)))->get();
Edit: I should probably explain first.
DB::select() is primarily used for the database builder in order to chain onto other chain-able functions, and not for doing your whole query.
You could use DB::statement to provide a new custom SQL query in it, but you also have to specify that the contents of the statement()'s parameter will be a raw query. Hence the DB::raw
Alternatively you could take advantage of Eloquent or Laravel's query builder by creating an Eloquent model called Document in app/models with contents as:
class Document extends Eloquent {}
and swap out your query above with:
$doc_options = Document::select('document_description')->where('user_id','=',$userid)->get()

You are passing an object into the Form::select() helper, and it is expecting an array.
Instead, Laravel has tools built in to do just this. See the lists() method in the Laravel docs under Selects:
public function uploadDocs($userid)
{
$doc_options = DB::table('document')->where('user_id', $userid)->lists('document_description');
return View::make('uploaddocs')->with('doc_options', $doc_options);
}
That should be it.

Related

Why is it not possible to use groupBy() in an eager loading query - Laravel

ErrorException:
stripos() expects parameter 1 to be string, object given
For the groupBy() call in the with() method
$user = User::with([
'pricelists' => function($query) {
$query->groupBy(function($var) {
return Carbon::parse($var->pivot->created_at)->format('m');
});
}
])->where('id', $id)->get();
I already saw a few posts talking about how to manage this problem and that it shall not be possible to use groupBy() in eloquent but I do not really understand why...
To be clear:
User and Pricelist model got a many-to-many relationship with the default timestamps() method. I am trying to get the downloaded pricelists grouped by their months they were downloaded from the current user.
After a few attempts I just deleted the above shown => function($query... statement from the with() method and just left the with(['pricelist']) to fetch all datasets and tried this:
$user->pricelists = $user->pricelists->groupBy(function($var) {
return Carbon::parse($var->pivot->created_at)->format('m');
});
return $user->pricelists;
And it works fine and returns an array with multiple arrays for each month... But returning it like this:
return $user;
returns just 1 array with all entries... I do not really get the sense behind it right now...
The two groupBy() method that you are using in the two code you provide are totally different methods.
The first groupBy() where you use it in the callback is actually being called by $query which is a query builder object. The groupBy() here is used to add SQL GROUP BY Statement into the query. And as per the documentation, it only take string variables as parameter.
The groupBy() in your second code is being called by $user->pricelists which is a laravel eloquent collection. The groupBy() method here is actually from the base collection class and is used to group the items inside the collection into multiple collections under the different key defined by the parameter passed to the function. Please read the documentation here.
For your case, the second groupBy() is the one you should be using since you plan to use a callback and will allow you to use more complicated logic.

Catch and save elements in Laravel, not by primaryKey

I need to get an element from the database, but I can not get it by the FIND method, since FIND only finds it by the primaryKey and what I need is not by my primaryKey. So I did like this:
$user = Pac::find($request->pac_id);
$element = query()->where('med_cart', $user->pac_id)->get();
$element->med_obs = $request->med_obs;
$element->save(); // error
Now I need to save this element, however, I can not use the SAVE method, as I believe it is fully connected with FIND and FINDORFAIL (if anyone knows, explain to me which methods I can use the SAVE method).
How can I save them the way I did? Or is there some other way to do it?
Because I need to get the element with a data other than the primaryKey and then save it, then I can not use FIND or FINDORFAIL, I think.
The function ->find() returns an Eloquent Model instance and you can then call ->save() on the model instance.
You're using ->get() which returns a Collection.
To update your query (that may target one or more entries) just perform the update statement directly from the QueryBuilder by replacing ->get() with ->update(['med_obs' => $request->med_obs]).
Be aware that when doing this you are now using Fluent queries, instead of eloquent. This means that any logic you may have defined in the boot function of your model is not evaluated.
If you are certain that you only have a single result you can append ->first() to your query, which will return a Model of the first result that matches your ->where clause. You can then call ->save() on it:
$user = Pac::find($request->pac_id);
$element = query()->where('med_cart', $user->pac_id)->first();
$element->med_obs = $request->med_obs;
$element->save();

Laravel blade method latest doesn´t exist on user model

In my user model (App\User.php), I declare following relationship:
public function actionables() {
return $this->hasMany(Actionable::class, 'owner_id', 'id');
}
In my migration scheme for the actionables table, I specify following foreign key:
$table->foreign('owner_id')->references('id')->on('users')->onDelete('cascade');
When I call
{{ auth()->user()->actionables->where('act_type', 'order')->latest()->content }}
In a blade view, I get following error message:
Method Illuminate\Database\Eloquent\Collection::latest does not exist.
I´ve tried using ->get() and using other way´s of accessing the user model (Auth::user), but nothing has solved the problem so far.
The distinction that the other answers are glossing over is using the query builder vs using a collection. When you call the relationship using a property Eloquent will fetch all the results then return a collection (which is basically just a beefed up array). So when you do
auth()->user()->actionables
Laravel executes the SQL Query then returns all the results as a collection.
SELECT * FROM actionables WHERE owner_id = ?
The collection class has a where method that functions similarly to the query builder method, but it's important to realize that it's performing the search in PHP not SQL because the query has already been executed and can't be changed anymore. latest() exists on the query builder, but not the collection which is where your error is coming from.
To leverage the relationship in the query builder you need to call the relationship as a function. user()->actionables()
auth()->user()->actionables()->where('act_type', 'order')->latest()->first()
The above will execute the SQL query then return just the record you're looking for.
SELECT * FROM actionables WHERE act_type = order AND WHERE owner_id = ? ORDER BY created_at DESC LIMIT 1
latest not exist not within Collection methods.
to get the last element of your database query you should apply this query:
*Note that you should have created_at within the Actionable table.
auth()->user()->actionables()->where('act_type', 'order')->orderBy('created_at', 'desc')->first()->content
You should use the query builder actionables() not the collection actionables, i.e:
{{ auth()->user()->actionables()->where('act_type', 'order')->latest()->first()->content }}
It must be ->last() not ->latest()
{{ auth()->user()->actionables->where('act_type', 'order')->last()->content ?? ""}}
Collection does not have the latest method, it's the query builder that has that method.
Try last instead.
Ref: https://laravel.com/docs/5.8/collections#available-methods

Laravel -> Make query based on model's method result

I have 2 tables and models.
So, 1 CV has Many Diplomas. Relationship is defined in models.
In my edit action :
$cv = Cv::where('link', '=', $link)->firstOrFail();
Then If I'm calling relationship function diplomas like here :
$cvDiploms = $cv->diplomas;
return $cvDiploms;
It returns me array of JSON objects.
Now, I'm trying to make a query like :
$deletedDiplomas = $cv->diplomas->whereNotIn('image', $request['test-diploma'])->get();
It returns me that error :
Missing argument 1 for Illuminate\Support\Collection::get(), called in
/home/name/project/app/Http/Controllers/CvsController.php on line 272
and defined
How should I call that query to get all Cv's diplomas, where 'image' is not in $request['test-diploma'] ?
$cv->diplomas automatically calls get() on the query, so it returns a collection. You are then calling get() again, but the Collection method get() requires an argument.
You need to write $cv->diplomas() (referencing the function not the attribute) to fetch the query, which you can then filter before calling get()
$deletedDiplomas = $cv->diplomas()->whereNotIn('image', $request['test-diploma'])->get();
You are probably trying to make a query on an array object. You should use the relation itself to make the query. Try this:
$deletedDiplomas = $cv->diplomas()
->whereNotIn('image', $request['test-diploma'])
->get();

Laravel 5 Model orderBy?

I see you can call my MyModel::all() and then call "where" "groupBy" .. etc
I cant seem to find orderBy as this Q & A suggest..
Has this been removed in Laravel 5?
I've tried looking through the docs for a reference in Collection and Model but I'm assuming these are actually just modifiers for the collection returned and not actually modifying the query statement..
The only way I know of using order by is
\DB::table($table)->where($column)->orderBy($column);
Is that the only way to order your database select when executing a query?
You can actually just use it like where and groupBy:
$result = MyModel::orderBy('name', 'desc')->get();
Note that by calling MyModel::all() you're already executing the query.
In general you can pretty much use every method from the query builder documented here with Eloquent models. The reason for this is that the model proxies method calls (that it doesn't know) to a query builder instance:
public function __call($method, $parameters)
{
// irrelevant code omitted
$query = $this->newQuery();
return call_user_func_array(array($query, $method), $parameters);
}
$this->newQuery() creates an instance of the query builder which then is used to actually run the query. Then when the result is retrieved the model/collection is hydrated with the values from the database.
More info
Eloquent - Laravel 5 Docs
Illuminate\Database\Eloquent\Builder - API docs
And also the regular query builder (since quite a few calls get passed from the eloquent builder)
Illuminate\Database\Query\Builder - API docs
You can achieve this with the following solution:
$result = ModelName::orderBy('id', 'desc')->get();
You can do it by using sort keys
Model::all()->sortKeys()
(or)
Model::all()->sortKeysDesc()

Categories