Eloquent 'with()' just 1 record? - laravel

I have a many-to-one relation between two tables, but how do you use the 'with()' method to bring in just one associated record, rather than all of them? (that whose date is nearest the current date, for example)?

You can use a closure on the with() method to query the relation.
$users->with(['address' => function($q) use ($someVariable) {
$q->where('zip', '=', $someVariable);
});

There is a ->first() method. Which will give you the first result only. This replaces ->get().
https://laravel.com/docs/5.3/eloquent#retrieving-single-models

You can use a with() method in following way.
$user->with(['address'])->findWhere(['zip'=>$someVariable]);

Related

Error Call to a member function where() on array Laravel

I want to do filtering from the data that I display, but there is a problem when I add where to my data.
the plan in the future I want to add if isset $request name, date and others. but was constrained at this one point.
Thank you for helping to answer in advance
$matchs =Matchs::where('type', 'sparring')->where('status','Pending')->whereNull('deleted_at')->get()->toArray();
$data=[];
foreach ($matchs as $key) {
$lawan = Matchs::where('id', $key['id'])->first()->ToArray();
$pertandingan = Sparring::where('match_id', $key['id'])->first()->ToArray();
$dua_arah = MatchTwoTeam::where('match_id', $key['id'])->first()->ToArray();
$tim = Team::where('id', $dua_arah['home_team'])->first()->ToArray();
$transfer['name']=$tim['name'];
$transfer['city']=$lawan['city'];
$transfer['field_cost']=$pertandingan['field_cost'];
$transfer['referee_cost']=$pertandingan['referee_cost'];
$transfer['logo_path']=$tim['logo_path'];
$transfer['nama_lapangan']=$lawan['nama_lapangan'];
$transfer['date']=$lawan['date'];
array_push($data,$transfer);
array_push($data,$pertandingan);
}
$data->where('name', 'LIKE', '%'.'football'.'%')->get()->toArray();
$data = array_search('football', array_column($data, 'name'));
$tittle="Sparring";
return view('mode.sparring',[
'tittle' => $tittle,
'data' => $data,
]);
You are trying to call where in an array which is not possible.
As you can see in the first line of your code you are calling where method in your model class. Like Matchs::where('type', 'sparring'), this is possible because Matchs is a Model class.
Now you can run where even if you are using array. You can convert that day in collection and then use array on that collection.
As below:
collect($data)->where('name', 'football')->toArray();
Here collect() will convert the $data array to collectio and then run the where() method in collectio then toArray() will change it back to array. But unfortunately there is no like operator possible in collection class. See the list of available method in Laravel collection here: https://laravel.com/docs/8.x/collections#available-methods
There is a way to do what you are trying to do. As far as I understand you want to filter the Matches where the Team name has footbal in it. You can do it like this:
Matchs::where('type', 'sparring')
->where('status','Pending')
->whereNull('deleted_at')
->whereHas('team', function($team) {
return $team->where('name', 'LIKE', '%'.'football'.'%')
})
->get()
->toArray();
So, here we can get the only those Mathes that has the Team that has the name contains football.
Few suggestion for you as seems you are new in Laravel:
Model name should be singular instead of plural, so the model class Matchs should be Match. Your name for team's model is Team is correct.
Avoid using toArray() because you won't need it. When you call get() it will return object of collection which more readable and powerful then array in most cases.
The code I suggested to use the like using whereHas will only work if you have propery defined your team relation in your Matchs class. So, defining your relationships in model is also important. If you do so, you don't even need the for loop and all those where in other model in that loop. You can do it in one query with all the relationships.

How to select specific columns in laravel eloquent

lets say I have 7 columns in table, and I want to select only two of them, something like this
SELECT `name`,`surname` FROM `table` WHERE `id` = '1';
In laravel eloquent model it may looks like this
Table::where('id', 1)->get();
but I guess this expression will select ALL columns where id equals 1, and I want only two columns(name, surname). how to select only two columns?
You can do it like this:
Table::select('name','surname')->where('id', 1)->get();
Table::where('id', 1)->get(['name','surname']);
You can also use find() like this:
ModelName::find($id, ['name', 'surname']);
The $id variable can be an array in case you need to retrieve multiple instances of the model.
By using all() method we can select particular columns from table like as shown below.
ModelName::all('column1', 'column2', 'column3');
Note: Laravel 5.4
You first need to create a Model, that represent that Table and then use the below Eloquent way to fetch the data of only 2 fields.
Model::where('id', 1)
->pluck('name', 'surname')
->all();
Also Model::all(['id'])->toArray() it will only fetch id as array.
Get value of one column:
Table_Name::find($id)->column_name;
you can use this method with where clause:
Table_Name::where('id',$id)->first()->column_name;
or use this method for bypass PhpStorm "Method where not found in App\Models":
Table_Name::query()->where('id','=',$id)->first()->column_name;
in query builder:
DB::table('table_names')->find($id)->column_name;
with where cluase:
DB::table('table_names')->where('id',$id)->first()->column_name;
or
DB::table('table_names')->where('id',$id)->first('column_name');
last method result is array
You can use get() as well as all()
ModelName::where('a', 1)->get(['column1','column2']);
From laravel 5.3 only using get() method you can get specific columns of your table:
YouModelName::get(['id', 'name']);
Or from laravel 5.4 you can also use all() method for getting the fields of your choice:
YourModelName::all('id', 'name');
with both of above method get() or all() you can also use where() but syntax is different for both:
Model::all()
YourModelName::all('id', 'name')->where('id',1);
Model::get()
YourModelName::where('id',1)->get(['id', 'name']);
To get the result of specific column from table,we have to specify the column name.
Use following code : -
$result = DB::Table('table_name')->select('column1','column2')->where('id',1)->get();
for example -
$result = DB::Table('Student')->select('subject','class')->where('id',1)->get();
use App\Table;
// ...
Table::where('id',1)->get('name','surname');
if no where
Table::all('name','surname');
If you want to get a single value from Database
Model::where('id', 1)->value('name');
Also you can use pluck.
Model::where('id',1)->pluck('column1', 'column2');
You can use Table::select ('name', 'surname')->where ('id', 1)->get ().
Keep in mind that when selecting for only certain fields, you will have to make another query if you end up accessing those other fields later in the request (that may be obvious, just wanted to include that caveat). Including the id field is usually a good idea so laravel knows how to write back any updates you do to the model instance.
You can get it like
`PostModel::where('post_status', 'publish')->get(['title', 'content', 'slug', 'image_url']`)
link
you can also used findOrFail() method here it's good to used
if the exception is not caught, a 404 HTTP response is automatically sent back to the user. It is not necessary to write explicit checks to return 404 responses when using these method not give a 500 error..
ModelName::findOrFail($id, ['firstName', 'lastName']);
While most common approach is to use Model::select,
it can cause rendering out all attributes defined with accessor methods within model classes. So if you define attribute in your model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the user's first name.
*
* #param string $value
* #return string
*/
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
}
And then use:
TableName::select('username')->where('id', 1)->get();
It will output collection with both first_name and username, rather than only username.
Better use pluck(), solo or optionally in combination with select - if you want specific columns.
TableName::select('username')->where('id', 1)->pluck('username');
or
TableName::where('id', 1)->pluck('username'); //that would return collection consisting of only username values
Also, optionally, use ->toArray() to convert collection object into array.
If you want to get single row and from the that row single column, one line code to get the value of the specific column is to use find() method alongside specifying of the column that you want to retrieve it.
Here is sample code:
ModelName::find($id_of_the_record, ['column_name'])->toArray()['column_name'];
If you need to get one column calling pluck directly on a model is the most performant way to retrieve a single column from all models in Laravel.
Calling get or all before pluck will read all models into memory before plucking the value.
Users::pluck('email');
->get() much like ->all() (and ->first() etc..) can take the fields you want to bring back as parameters;
->get/all(['column1','column2'])
Would bring back the collection but only with column1 and column2
You can use the below query:
Table('table')->select('name','surname')->where('id',1)->get();
If you wanted to get the value of a single column like 'name', you could also use the following:
Table::where('id', 1)->first(['name'])->name;
For getting multiple columns (returns collection) :
Model::select('name','surname')->where('id', 1)->get();
If you want to get columns as array use the below code:
Model::select('name','surname')->where('id', 1)->get()->toArray();
If you want to get a single column try this:
Model::where('id', 1)->first(['column_name'])->column_name;

Laravel whereDoesntHave() - multiple OR conditions

In Laravel 4.2 I have a model called Product with many-to-many relationshis to other models like Country or Category. I want to filter out products that are "incomplete", which means they have no connected countries or no connected categories. I can use whereDoesntHave() method to filter out one relation. When I use it two times in one query it creates AND condition, but I need OR. I can't find orWhereDoesntHave() method in API documentation. I can't pass multiple relations as arguments because it expects first argument to be a string.
I need something like this:
$products = Product::whereDoesntHave('categories')->orWhereDoesntHave('countries')->get();
Is there any way to achive whereDoesntHave() with multiple OR conditions?
You can use doesntHave and specify the boolean operator:
$products = Product::doesntHave('categories')->doesntHave('countries', 'or')->get();
Actually you only need whereDoesntHave if you want to pass in a closure to filter the related models before checking if any of them exist. In case you want to do that you can pass the closure as third argument:
$products = Product::doesntHave('categories', 'or', function($q){
$q->where('active', false);
})->doesntHave('countries', 'or')->get();
Since Laravel 5.5 there is an orWhereDoesntHave function.
You may use it like this
Product::whereDoesntHave('categories', function($q){ //... })
->orWhereDoesntHave('countries', function($q){//...})
->get();
From you example it seems that you are not using a where clause, so you may just use
Product::doesntHave('categories')
->orDoesntHave('countries')
->get();
Use
Product::whereDoesntHave('categories')->doesntHave('countries', 'or')->get();
Laravel Source Code:
whereDoesntHave https://github.com/illuminate/database/blob/master/Eloquent/Builder.php#L654
calls
https://github.com/illuminate/database/blob/master/Eloquent/Builder.php#L628
internally.
Let’s say we have Authors and Books, with 1-n relationship – one Author can have one or many Books. Here’s how it looks in app\Author.php:
public function books()
{
return $this->hasMany(\App\Book::class, 'author_id');
}
Now, what if we want to show only those Authors that have at least one book? Simple, there’s method has():
$authors = Author::has('books')->get();
Similarly, there’s an opposite method – what if we want to query only the authors without any books? Use doesnthave():
$authors = Author::doesnthave('books')->get();
It’s not only convenient, but also super-easy to read and understand, even if you’re not a Laravel developer, right?

Laravel: Difference between where and whereHas

What is the difference between the two methods where() and whereHas()? They both seem to be quite similar in the laravel documentation.
The method where() behaves like a regular SQL WHERE query part.
The method has() uses foreign key relationships to return something which has something else. For instance, Student::has('classes')->get(); would return all students who have classes.
The method whereHas() is like a regular has(), but it lets you put constraints on the search. Unlike where(), this is done on the child table rather than the parent one. Here's an example:
$students = Student::where('name', 'Pingu') // constrains the students table
->whereHas('classes', function($query) {
$query->where('name', 'like', '%physics%'); // constrains the classes table
})->get();
In this highly realistic example, you'd want all students with a name of Pingu, who are taking some class in physics.

Eloquent ORM: Obtain a object, not an array of objects

I have this statement in Laravel 4:
$prepayment = Prepayment::where('hash', '=', $custom)->take(1)->get();
But this return an array of objects, and I want only one object, because there are only one result with the hash that I search.
How is the way to obtain only one object, not an array of objects?
Thanks!
Use the first() method instead of the get() method
$prepayment = Prepayment::where('hash', '=', $custom)->first();
This is a good article to learn more about how the eloquent orm works. http://laravel.io/topic/14/how-eloquent-relationship-methods-work It describes how the belongs to relationship will just give you one object whereas the has many relationship will give you an arrray of objects

Resources