How to solve Method orderBy does not exist on laravel? - laravel

I use this package : https://github.com/andersao/l5-repository
My user repository is like this :
public function getList($year)
{
$query = parent::findWhere(['year' => $year])
->orderBy('updated_at')
->paginate(10);
return $query;
}
When executed, there exist error like this :
Method orderBy does not exist.
Whereas I see in the documentation, there exist orderBy
How can I solve it?

If you'll look into the findWhere() method, you'll see that it executes query:
$model = $this->model->get($columns);
So, you'll not be able to use orderBy() or paginate() after findWhere().

findWhere exec the query and get your values using get().
try to change your code to this:
public function getList($year)
{
$query = parent::where('year', '=>', $year)
->orderBy('updated_at')
->paginate(10);
return $query;
}

use something like that for compound searches
$posts = $this->repository->scopeQuery(function($query){
return $query->orderBy('name','asc');
})->findByField('user_id',$dataForm['user_id']);

Related

Filter based on collection or sub-attribute

My user model has a 'prevregistration' attribute
public function prevregistration()
{
return $this->hasMany(Prevregistration::class, 'prevregistration_userid');
}
My prevregistraton model has a 'prev' attribute
public function prev()
{
return $this->hasOne(Prev::class,'prev_id', 'prevregistration_previd');
}
In my controller I show prevregistrations for the current user:
mynextprevs = Auth::user()->prevregistration ;
Now I want to only show prevregistrations from which the connected prev its prev_date in the future, like this:
$mynextprevs = Auth::user()->prevregistration::whereDate('prev_date', '>=', Carbon::today()->toDateString());
But then I get:
BadMethodCallException
Method Illuminate\Database\Eloquent\Collection::whereDate does not exist.
I also tried like this:
$mynextprevs = Auth::user()->prevregistration->prev::whereDate('prev_date', '>=', Carbon::today()->toDateString());
But then I get:
Property [prev] does not exist on this collection instance.
Should I/how can I filter the collection? I'm curious why Auth::user()->prevregistration->prev is not working, since that are attributes.
Thanks
You need to use the condition whereHas on your prevregistration
$mynextprevs = Auth::user()->prevregistration()->whereHas('prev',function($prev) {
$prev->whereDate('prev_date', '>=', Carbon::today()->toDateString());
})->get();
Notice we used the relation as a method prevregistration() to access it as a query builder and not as a collection hence the need for the ->get() at the end.

laravel: odd behavior when query is empty

I have a model
I call it this way:
Sight::filter(['type'=>'menu']);
and in model:
public function scopeFilter($query,$params)
{
return $query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
}
when there is one or more records, it works normally.
but when database is empty I get an odd behavior:
with dd(Sight::filter(['type'=>'menu']))
or
$query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
dd($query);
I got this result:
But with
dd(
$query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
)
I got Null so it is right!
how can I return Null? what is my wrong?
You shouldn't be calling first() inside of a scope - you are only meant to adjust the query by constraining it. You should call first() in your chain after applying the filter() scope. If you want to use the same syntax rather than chaining like that you would be best to define a custom static method.
public static function filter($params)
{
return self::wherePublish(1)
->whereIn_special(1)
->latest()
->first();
]
Also note that in your example your scope accepts an argument (and you pass it one) but it isn't actually used in your code.

Eloquent / Laravel - Putting a WHERE Clause on a Reference Table With Chained Relationships

I have the following relationship functions in my Job model:
public function resourceTypes(){
return $this->belongsToMany('ResourceType', 'job_requests');
}
public function resources(){
return $this->belongsToMany('Resource', 'jobs_resources')->withPivot('flow_type', 'resource_type_id');
}
I am able to get an object with data from both of the above relationships using:
$job = Job::findorfail($projectId);
$result = $job->with('resources.resourceTypes')->get();
I would like to put a where clause on the jobs_resources pivot table - specifically on the column flow_type.
How would I do this?
Try something like this:
$job = Job::with('resources' => function($q) {
$q->with('resourceTypes')->where('flow_type',2);
})->findorfail($projectId);
In above you will get only those resources with flow_type = 2
I ended up using the following statement:
Job::with(['resources' => function ($query){
$query->wherePivot('flow_type', '=', '1' );
}, 'resources.resourceTypes'])->where('id', $projectId)->firstOrFail();
$result = DB::table('job')
->join('job_resources', 'job.id', '=', 'job_resources.job_id')
->join('job_requests', 'job_resources.request_id', '=', 'job_requests.id')
->where('job_resources.flow_type', '=', CONDITION)
->get();
Your table data is not clear from your input, but this method (query builder) should work

Where NOT in pivot table

In Laravel we can setup relationships like so:
class User {
public function items()
{
return $this->belongsToMany('Item');
}
}
Allowing us to to get all items in a pivot table for a user:
Auth::user()->items();
However what if I want to get the opposite of that. And get all items the user DOES NOT have yet. So NOT in the pivot table.
Is there a simple way to do this?
Looking at the source code of the class Illuminate\Database\Eloquent\Builder, we have two methods in Laravel that does this: whereDoesntHave (opposite of whereHas) and doesntHave (opposite of has)
// SELECT * FROM users WHERE ((SELECT count(*) FROM roles WHERE user.role_id = roles.id AND id = 1) < 1) AND ...
User::whereDoesntHave('Role', function ($query) use($id) {
$query->whereId($id);
})
->get();
this works correctly for me!
For simple "Where not exists relationship", use this:
User::doesntHave('Role')->get();
Sorry, do not understand English. I used the google translator.
For simplicity and symmetry you could create a new method in the User model:
// User model
public function availableItems()
{
$ids = \DB::table('item_user')->where('user_id', '=', $this->id)->lists('user_id');
return \Item::whereNotIn('id', $ids)->get();
}
To use call:
Auth::user()->availableItems();
It's not that simple but usually the most efficient way is to use a subquery.
$items = Item::whereNotIn('id', function ($query) use ($user_id)
{
$query->select('item_id')
->table('item_user')
->where('user_id', '=', $user_id);
})
->get();
If this was something I did often I would add it as a scope method to the Item model.
class Item extends Eloquent {
public function scopeWhereNotRelatedToUser($query, $user_id)
{
$query->whereNotIn('id', function ($query) use ($user_id)
{
$query->select('item_id')
->table('item_user')
->where('user_id', '=', $user_id);
});
}
}
Then use that later like this.
$items = Item::whereNotRelatedToUser($user_id)->get();
How about left join?
Assuming the tables are users, items and item_user find all items not associated with the user 123:
DB::table('items')->leftJoin(
'item_user', function ($join) {
$join->on('items.id', '=', 'item_user.item_id')
->where('item_user.user_id', '=', 123);
})
->whereNull('item_user.item_id')
->get();
this should work for you
$someuser = Auth::user();
$someusers_items = $someuser->related()->lists('item_id');
$all_items = Item::all()->lists('id');
$someuser_doesnt_have_items = array_diff($all_items, $someusers_items);
Ended up writing a scope for this like so:
public function scopeAvail($query)
{
return $query->join('item_user', 'items.id', '<>', 'item_user.item_id')->where('item_user.user_id', Auth::user()->id);
}
And then call:
Items::avail()->get();
Works for now, but a bit messy. Would like to see something with a keyword like not:
Auth::user()->itemsNot();
Basically Eloquent is running the above query anyway, except with a = instead of a <>.
Maybe you can use:
DB::table('users')
->whereExists(function($query)
{
$query->select(DB::raw(1))
->from('orders')
->whereRaw('orders.user_id = users.id');
})
->get();
Source: http://laravel.com/docs/4.2/queries#advanced-wheres
This code brings the items that have no relationship with the user.
$items = $this->item->whereDoesntHave('users')->get();

Active Record and queries with CodeIgniter

I am using codeigniter for my application and i am a bit confused, I wrote some queries like that:
public function checkemail($email) {
$this->db->select('email')->from('user')->where('email', $email);
}
But in the manual of codeigniter ( http://codeigniter.com/user_guide/database/active_record.html ) they talk about $this->db->get();
Should I add it after the $this->db->select query?
My function works fine...
When should I use get() ?
Thanks you!
Yes, you'll need to run get() after the other methods. select(), from() and where() add their respective statements to the query, and get() actually runs the query and returns the result as an object.
In this case, you could just add it on to the end of the chain.
public function checkemail($email) {
$this->db
->select('email')
->from('user')
->where('email', $email)
->get();
}
If you want to work with the result afterwards, make sure that you are assigning it to a variable.
$user = $this->db
->select('email')
->from('user')
->where('email', $email)
->get();
If you use get("table_name") then you don't need to use from("table_name"). It's just an alternative syntax it seems.
From the user guide, all the way at the bottom it says: As shown earlier, the FROM portion of your query can be specified in the $this->db->get() function, so use whichever method you prefer.

Resources