I'm trying to extract the building of an Eloquent query as I want to reuse this code with many different models. In the controller, I have:
$inputs = Input::all();
$user = new Eloquent;
$result = Helpers::buildQuery($user, $inputs);
And the Helpers class:
<?php namespace ArgumentClub;
class Helpers {
public static function buildQuery(Eloquent $model, $inputs)
{
$limit = isset($inputs['limit']) ? $inputs['limit'] : 10;
$offset = isset($inputs['offset']) ? $inputs['offset'] : 0;
list($orderCol, $orderBy) = isset($inputs['order']) ? explode(",", $inputs['order']) : explode(",", 'created_at,DESC');
$result = $model
->orderBy($orderCol, $orderBy)
->skip($offset)
->take($limit)
->get();
return $result;
}
}
So, how can I pass in the model and have it query that model, returning the Eloquent collection?
Eloquent (which is an alias for Illuminate\Database\Eloquent\Model) is an abstract class. You can't instantiate it. Instead you have to do this:
$inputs = Input::all();
$user = new User;
$result = Helpers::buildQuery($user, $inputs);
The type restriction buildQuery(Eloquent $model, $inputs) will still work fine because User extends Eloquent and therefore is accepted by the method.
A little sidenote, you might also want to think about creating a base model to extend Eloquent and share functionality between all models.
You just have to pass your model class for exemple a User model which extend eloquent:
$inputs = Input::all();
$user = new User;
$result = Helpers::buildQuery($user, $inputs);
Just add the ungaurd() and regaud() before and after your seeder classes in run() method of DatabaseSeeder.php
\Illuminate\Database\Eloquent\Model::unguard();
//$this->call(UsersTableSeeder::class);
\Illuminate\Database\Eloquent\Model::reguard();
This solved my problem.
Related
i'm having an error with Eloquent (and Many to Many relationship).
This is my code:
$user = new Users;
$rs = $user
->company()
->where('company_role.users_id', $request->session()->get('usrid'))
->where('code', $request->company)
->first();
The query that Eloquent perform is this one:
select `companies`.*, `company_role`.`users_id` as `pivot_users_id`, `company_role`.`companies_id` as `pivot_companies_id`, `company_role`.`role_name` as `pivot_role_name` from `companies` inner join `company_role` on `companies`.`id` = `company_role`.`companies_id` where `company_role`.`users_id` is null and `company_role`.`users_id` = 1 and `code` = 12345678901 limit 1)"
How is this possible? Do you guys have any idea?
This is my Users model:
class Users extends Model
{
//table associated with model
protected $table = 'users';
protected $primaryKey = 'id';
public function company(){
return $this->belongsToMany('App\Companies','company_role')->withPivot('role_name');
}
}
It was a rookie error
i just changed this:
$rs = $user->company()->where('company_role.users_id',$request->session()->get('usrid'))->where('code',$request->company)->first();
into this:
$rs = $user->find($request->session()->get('usrid'))->company()->where('piva',$request->company)->first();
and everything works as expected.
Thanks to everyone!
First, define the variables
$user_id = $request->session()->get('usrid');
$user = User::find($user_id);
Then, you need to find the user and the companies they are attached, and an individual company with the search params
$companies = $user->company()->get();
$company = $user->company()->where('code', $request->company)->first();
I have the defaults users table which I've altered to have userable_type and userable_id. I have various models, eg BursaryAdministrator and BursaryProvider and users can belong to either.
BA/BP Model:
public function users() {
return $this->morphMany('App\Users', 'userable');
}
Users Model:
public function userable()
{
return $this->morphTo();
}
During my migration, I've created a default BursaryAdministrator and BursaryProvider and a couple of users. I want to assign them to each:
$bp = \App\BursaryProvider::first();
$user = User::find(2);
$bp->users()->associate($user);
$ba = \App\BursaryAdministrator::first();
$user = User::find(3);
$ba->users()->associate($user);
However, they're not linking as the userable_type / userable_id fields are null. I've tried both 'associate' and 'attach'.
Whats the correct what to do this?
You could try to save() the user after association, i.e.:
$bp = \App\BursaryProvider::first();
$user = User::find(2);
$bp->users()->associate($user);
$user->save()
$ba = \App\BursaryAdministrator::first();
$user = User::find(3);
$ba->users()->associate($user);
$user->save()
Ok, so this was the correct way at the end of the day:
$bp = \App\BursaryProvider::first();
$user = User::find(2);
$user->userable()->associate($bp);
$user->save();
$ba = \App\BursaryAdministrator::first();
$user = User::find(3);
$user->userable()->associate($ba);
$user->save();
Thanks to #dparoli for pointing me in the right direction.
I have 2 two tables: one is an admission and the other is a class table. I am saving class id in admission class field of admission table by json_encode method.
My controller
public function store(Request $request)
{
$inputs = $request->all();
$admission = new Admission;
$admission->school_id = Auth::User()->id;
$admission->admission_classes=json_encode($inputs['admission_classes']);
$admission->save();
}
My index function
public function index(Request $request) {
$school_id= Auth::user()->id;
$admissions= Admission::where('school_id',$school_id)->orderBy('id','desc')->paginate(10);
return view('frontend.index',compact('admissions','active_class'));
}
My view
#foreach($admissions as $i => $admission)
{{ $admission->admission_classes }}
#endforeach
I am getting data in this way:-
["1","2","4","5","6","7","8","9"]
But I want to get in this format:
Nursery,Class 1, Class2, Class3 etc
My class controller
class Classes extends Authenticatable
{
use EntrustUserTrait;
use Billable;
use Messagable;
protected $fillable = [
'name','status'
];
}
You need to save integer value in as json array and do the following code
$integerIDs = array_map('intval', $inputs['admission_classes']);
$admission->admission_classes= json_encode($integerIDs);
public function index(Request $request){
$admissions = DB::select('SELECT a.*, GROUP_CONCAT(c.name) as classes FROM academy as a LEFT JOIN class c ON JSON_CONTAINS(a.classes, CAST(c.id as JSON), '$') WHERE a.school_id =2 GROUP BY a.id');
$admissions = $this->arrayPaginator($admissions, $request);
return view('frontend.index',compact('admissions','active_class'));
}
public function arrayPaginator($array, $request)
{
$page = Input::get('page', 1);
$perPage = 10;
$offset = ($page * $perPage) - $perPage;
return new LengthAwarePaginator(array_slice($array, $offset,
$perPage, true), count($array), $perPage, $page,
['path' => $request->url(), 'query' => $request->query()]);
}
I have not checked the code hope this will help u to continue.......
The best way to achieve this would be to have a one-to-many relationship with App\Classes.
However, since you already have something up and running, I would probably do it like this.
First, I would cast admission_classes to an array. This makes sure that admission_classes will always be casted to an array whenever it is fetched. It makes it easier for us to work with it.
protected $casts = [
'admission_classes' => 'array'
];
Finally, while fetching your admission records, you would also need to map over it and hydrate the Classes from its ids. This is how I'd try to achieve it.
$admissions = Admission::where('school_id',$school_id)
->orderBy('id','desc')
->paginate(10)
->map(function($admission) {
return array_map(function($class) {
$class = Classes::find($class);
return isset($class) ? $class->name : '';
}, $admission->admission_classes);
});
You will notice that I wrapped the Classes::find() method into the optional() helper. This is because, in case, a record is not found, it will not fail.
Finally, to print your class names in your blade, you would do something like this:
implode(',', $admission->admission_classes);
I am using Laravel 5.5.13.
I have a model called Thumb. This thumb is related to two things in a many-to-one relationship: Player and Comment.
I currently do things like this:
public function store(Request $request, Entity $entity, Player $player)
{
$thumb = new Thumb($request->all());
$thumb->player_id = $player->id;
$entity->thumbs()->save($thumb);
return response()->json($thumb, 201);
}
We see how I have to set $thumb->player_id AND I don't have to set the entity_id because I am doing $entity->thumbs()->save
Is there a way to do $entityAndPlayer->thumbs()->save? Or is the way I did it above the recommend way?
You cannot use relationships to set 2 foreign columns so they way you showed is the correct one. However you can make it a bit cleaner in my opinion.
Into Thumb model you could add:
public function setPlayer(Player $player)
{
$this->player_id = $player->id;
}
and then instead of:
$thumb->player_id = $player->id;
you could use:
$thumb->setPlayer($player);
Or you could add create setPlayerAttribute method and finally instead of:
$thumb = new Thumb($request->all());
$thumb->player_id = $player->id;
use just:
$thumb = new Thumb($request->all() + ['player' => $player]);
You can't save multiple relationships at once but, for many to one associations you can use the method associate() (Laravel docs) to save using the belongs to part of the relationship, for example:
public function store(Request $request, Entity $entity, Player $player)
{
$thumb = new Thumb($request->all());
$thumb = $thumb->save();
$thumb->player()->associate($player);
$thumb->entity()->associate($entity);
return response()->json($thumb, 201);
}
I'm having this strange behavior in Laravel 5.1 where when I call the relation of an eloquent model more than once within the same code execution, then the second time it doesn't have the data.
class Items extends Eloquent {
public $table = 'items'
public function subItems() {
return $this->hasMany(Item::class, 'items_id');
}
}
class Item extends Eloquent {
public $table = 'items_item'
public $fillable = ['items_id'];
}
$items = Items::create();
Item::create([
'items_id' => $items->id,
]);
Item::create([
'items_id' => $items->id,
]);
// works
$first = $items->subItems;
// no data
$second = $items->subItems;
// works
$third = $items->subItems()->get();
Is this normal behavior? Do i have to somehow reset something before calling the relation again?
I don't know the purpose of your repeated same action. If your $first,$second,$third variables are in same function, don't repeat it again.
Instead use,
$first = $items->subItems;
$second = $first;