Paginate table with HasMany relation in cakephp 3 beta - has-many

I have advertisements table with (group_id,member_id,city_id) fields. This is my GroupsController->view method.
public function view($id = null) {
$group = $this->Groups->get($id);
$this->paginate = ['conditions'=>['group_id'=>$id] , 'contain'=>['Members', 'Cities']];
$advertisements = $this->paginate($this->Groups->Advertisements);
$this->set(compact('group' , 'advertisements'));
}
It generates this warning in addition to the true result.
Warning (4096): Argument 1 passed to Cake\Controller\Component\PaginatorComponent::validateSort() must be an instance of Cake\ORM\Table, instance of Cake\ORM\Association\HasMany given, called in D:\xampp\htdocs\project\vendor\cakephp\cakephp\src\Controller\Component\PaginatorComponent.php on line 153 and defined [CORE\src\Controller\Component\PaginatorComponent.php, line 301]
What is wrong?

The magic property getters return \Cake\ORM\Association instances, if you need the actual \Cake\ORM\Table object, use Association::target().
$this->Groups->Advertisements->target()

Related

Laravel, property not found

Trying to get property from a object in laravel. I have this:
public function index()
{
$firmen = Companies::all();
$allcountcompanies = Companies::count();
$agent = Agent::find($firmen->agent_firma_id);
return view('companies',compact(['firmen'],['allcountcompanies'],['agent']));
}
The Exeption gives me that:
Property [agent_firma_id] does not exist on this collection instance.
But when i put the id eg 1001 it shows corrent entry in db field.
What i0'm doing wrong?
Info:
CompaniesController.php (table: br_firma)
AgentController.php (table: br_firma_agents)
Table "br_firma_agents" contains a foreign_key from table "br_firma".
You are getting id from collection.
$firmens = Companies::all();
it return collection you may be use it useing loop and get one by one data as
for($firmens as $firmen){
$agent = Agent::find($firmen->agent_firma_id);
}
Or you create relation between Company and agent as,
In company model define relation as
public function agents(){
return $this->hasMany(Agent::class);
}
and in agent model define relation as
public function company(){
return $this->belongsTo(Companies::class);
}
and then call it as in controller,
$data = Companies::with('agents')->get();
You are trying to access an agent_firma_id from a collection of companies, you could first use a loop on that collection,or use an index on that collection,
you could try
$firmens = Companies::all();
foreach($firmens as $firmen){
$agent = Agent::find($firmen->agent_firma_id);
}

How to make conditions in a laravel query, based on returned value of a helper function

I'm using Laravel 5.7. I have a 'Match' model whose first participant name is returned from a helper function getFirstParticipant(Match $match).
I am trying to get certain matches from DB whose first participants are e.g. 'John'. Is it possible that I use Eloquent query functions to do so for example something like this?
Match::where('firstParticipant', 'John')
or any other solutions?
I am copying my helper function below if it can help to declare the problem:
function getFirstParticipant(Match $match)
{
$structure_id = $match->structure_id;
$seed = $match->matchResult->first_seed;
$placement = Placement::where('structure_id', $structure_id)->where('seed', $seed)->first();
return !empty($placement->player_id) ? $placement->player->username : $placement->team->name;
}
Just sub a variable into the second parameter.
$first = getFirstParticipant(Match $match);
Match::where('firstParticipant', $first->first_name)->get();
Obviously I'm assuming some variable names here such as first_name. But you should be able to follow that. Just use your helper to return a model value and insert that returned value as the second parameter of the where argument.
No, there is no way. Database design issues aside, the only way I can see this working is by using collection methods.
Match::get()->filter(function ($match) {
return $match->firstParticipant == 'John'; // Or is it getFirstParticipant($match) ?
})->all();
# Laravel 6.x introduces LazyCollections
Match::cursor()->filter(function ($match) {
return $match->firstParticipant == 'John'; // Or is it getFirstParticipant($match) ?
})->all();

Laravel Scope with join query

What im trying to do is to make this join into a scope function
$workorders =\DB::table('users')->leftjoin('work_orders','users.id','=','work_orders.user_id')->select('users.id','users.name','users.email','users.status','work_orders.cod','work_orders.deadline'->where('users.id','=','1');
$workorders = $workorders->get();
This is what I've tried with no success...
public function scopeOrders($query){
return $query->join('work_orders','users.id','=','work_orders.user_id')
->select('users.id','users.name','users.email','users.status','work_orders.cod','work_orders.deadline')
->where('users.id','=','1');
}
Expected result using the scope in a query
$usersWO = User::Orders()->get();
The only difference between $workorders = $workorders->get(); and $usersWO = User::Orders()->get(); is the output format. They both are bug-free.
A dd() on the former outputs a collection of stdClass objects with record values as properties.:
A dd() on the latter outputs a collection of models:
To modify the output of the second to look exactly like the first, you'll have to modify the client code since scopes return collections of models.
$usersWO = User::Orders()->get()->map(function ($user) {
return (object) $user->getAttributes();
});

Laravel get result from query in side query by Eloquent in one object

I have two tables:
main_presentations
so here i have "id" and "isEnabled";
child_presentations
And here i have "id" , "isEnabled" and "idParent";
I want to select in one object this is my code:
public function MainSlider(MainPresentation $MainPresentations, ChildPresentation $ChildPresentations)
{
$MainPresentations = MainPresentation::where('isEnabled', true)->get();
foreach ($MainPresentations as $MainPresentation) {
$AnArray[] = ChildPresentation::where([
['idParent', $MainPresentation['id']],
['isEnabled', true]
])->get();
}
return $AnArray;
}
but this is the result:
enter image description here
What you are doing is executing a query per result, which can be ineffective when it starts getting bigger.
You can:
Use querybuilder
As it follows, you just build a query starting on ChildPresentation, set a relation to MainPresentation table by id and get the collection
public function MainSlider()
{
$childPresentations = ChildPresentation::join('main_presentations','main_presentations.id','child_presentations.idParent')
->where('child_presentations.isEnabled', true)->where('main_presentations.isEnabled', true)->get();
return $childPresentations;
}
If you want all the MainPresentations with their respective ChildPresentations, only the enables ones.
You can take advantage of Laravel relationships and eager loading.
https://laravel.com/docs/5.6/eloquent-relationships
First, set the relationships in your MainPresentation model
In MainPresentation.php
public function childPresentation {
return $this->hasMany('App\ChildPresentation', 'idParent', 'id');
}
Your MainSlider function would be:
(Btw, no idea why you're receiving two arguments if you're overriding them but doesn't matter)
public function MainSlider() {
$mainPresentations = MainPresentation::with(['childPresentations' => function ($advancedWith) {
child_presentation.isEnabled is true
$advancedWith->where('isEnabled', true);
}])
->where('isEnabled', true)->get()->toArray();
return $mainPresentations;
}
This will return an array of MainPresentations that contain an array of child_presentations, with all their childs.
This translates to two queries:
Select * from main_presentations where isEnabled = true;
Select * from child_presentations where isEnabled= true and id in (in the first query);
Laravel then does background work to create the structure you desire when you write ->toArray()
Note: If you have a $visible array in your MainPresentation model, be sure to add: 'childPresentation' to it, otherwise the toArray will not agregage the childs to the parent.
Second note: I advise following some standards whenever you're writing code, usually functions are named camelCase and variables are camelCase.

Laravel 5 Pivot Table Extra Field

What I’m trying to do is when a new candidate is created an extra field is automatically populated in the joining pivot table with a random sting.
Here is my pivot table:
Result Table (pivot)
id cert_number candidate_id qualification_id
1 ? 17 2
2 ? 17 1
3 ? 57 1
So in my candidate controller I have:
public function store(CandidateRequest $request)
{
$candidateInput = Input::get('candidates');
foreach ($candidateInput as $candidate)
{
$candidate = Candidate::create($candidate);
$candidate->centre()->attach(Auth::user()->centre);
$qualification_id = $request->input('qualification_id');
$candidate->qualification()->attach($qualification_id);
$cert_number = Str::random(10);
$candidate->qualification()->attach($cert_number);
}
return redirect('candidates');
}
It adds the centre_id and qualification_id perfectly but it won’t pull though the random sting into the cert_nubmer field.
In my Candidate model I have
public function result()
{
return $this->hasMany('App\Result')->withTimestamps();
}
public function qualification()
{
return $this->belongsToMany('App\Qualification', 'Results', 'candidate_id', 'qualification_id')->withPivot('status','cert_number','partial_claim')->withTimestamps();
}
and in my result model:
public function candidate()
{
return $this->belongsTo('App\Candidate')->withTimestamps();
}
public function qualification()
{
return $this->belongsTo('App\Qualification');
}
Can anyone see where Im going wrong?
Thanks.
attach does not work like that.
Let me take out two lines of code:
$candidate->qualification()->attach($qualification_id);
$candidate->qualification()->attach($cert_number);
You are trying to add the $cert_number as a qualification_id, which is why it fails. When you do this, how is Laravel supposed to know that the second line ($cert_number) is an extra pivot column? It doesn't. You have two lines of code that are exactly the same so you can't expect Laravel to know that the second line should do something different.
When you want to insert extra data into other pivot columns, you need to pass them as an array in the second argument. Something like this:
$candidate->qualification()->attach($qualification_id, ['cert_number' => $cert_number]);

Resources