Lumen Model::find() does not select on primary key - php

I want to select an item from the table board by it's PK which is boardId.
However the Board::find(2) or Board::find(1) returns all items, regardless of given parameter.
I have the following table:
With corresponding Lumen Model:
class Board extends CustomModel
{
protected $fillable = [
'userId', 'boardName', 'private'
];
protected $primaryKey = 'boardId';
protected $table = 'board';
}
Custom Model is:
abstract class CustomModel extends Model
{
use Authenticatable, Authorizable;
const CREATED_AT = 'createdAt';
const UPDATED_AT = 'updatedAt';
}
Calling it with:
$boardId = 2;
return Board::find($boardId)->get();
Also tried:
$boardId = 2;
return Board::find($boardId)->first();
And the following:
$boardId = 2;
return Board::find($boardId)->toSql();
Returns: select * from 'board'. So there is no where boardId = ? or something, which is the problem. What am I doing wrong ?
I'm running PHP 7.2.0 and Lumen 5.5.2. Queries on other models work fine.

You've said you're calling it with get():
return Board::find($boardId)->get();
But you shouldn't add get() because it will return a collection of all objects. Just do this:
return Board::find($boardId);

Just erase the ->get() method this will works for you
I hope be useful

Related

How to limit query after with() method in laravel

i have 2 models. PostModel and CategoriesModel.
class PostModel extends Model
{
protected $table='posts';
protected $primaryKey = 'id';
protected $guarded=['id'];
public function categories()
{
return $this->belongsTo(CategoriesModel::class);
}
}
class CategoriesModelextends Model
{
protected $table='categories';
protected $primaryKey = 'id';
protected $guarded=['id'];
public function posts()
{
return $this->hasMany(PostModel::class);
}
}
I want to get 6 categories with 10 posts.
I used this code in my controller
$categories = CategoriesModel::with(['pages' => function($query) {
$query->limit('10');
}])->take("6")->get();
but this code is wrong. it applies to all records. But the truth is that this query applies per one categories. please help me.thanks
there is a laravel package specialized in this called Eloquent Eager Limit:
after installing it:
composer require staudenmeir/eloquent-eager-limit:"^1.0"
you should use it inside the models that would apply limited eager loading:
class PostModel extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
// ........
}
class CategoriesModel
extends Model
{
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
// ........
}
now this query will get the result you want:
$categories = CategoriesModel::with(['pages' => function($query) {
$query->limit('10');
}])->take("6")->get();
For eager loading you can do like this with map operation :
$categories = CategoriesModel::with('pages')->take(6)->get()
->map(function($q)
{ $q->pages = $q->pages->take(10); // take only 10 query
return $q;
}
);
The reason the above approach is necessary is because the constrained eager loading query roughly translates to SQL like:
Query to select Categories:
select * from `categories`
limit 6;
Query to fetch relation
select * from `categories`
inner join `posts` on `categories`.`id` = `posts`.`category_id`
where `posts`.`category_id` in (id's from categories query)
limit 10;
First of all your relation name is wrong in your controller. Update your category model by the following code:
public function ten_posts()
{
return $this->hasMany(PostModel::class)->take(10);
}
then update your controller with the following code:
$categories = CategoriesModel::with('ten_posts')->take(6)->get();
Try like this -
$categories = CategoriesModel::with(['pages' => function($query) {
$query->take('10');
}])->take("6")->get();

Laravel relation displaying null on eager load

A Laravel relation is displaying null on eager load. However, it works when the relation is accessed normally.
class Student extends Model
{
use SoftDeletes;
public $incrementing = false;
protected $primaryKey = 'id'; // or null
protected $guarded = [];
public function document()
{
return $this->hasOne('App\Model\Document');
}
public function contact()
{
return $this->hasOne('App\Model\Contact');
}
}
The contract relation returns null when I use the following.
Student::with('contact')->get()
However it works when I do the following. What could be the cause of this?
$student = Student::findOrFail($id);
$contact = $student->contact;
Student::with('contact')->get(); returns a Collection of Student instances, which you can loop and access the contact relationship:
$students = Student::with('contact')->get();
foreach($students AS $student){
dd($student->contact);
// Can be `null` or an instance of `Contact`
}
When you call Student::findOrFail($id);, you're getting a single instance of Student, which you can directly access contact:
$student = Student::with('contact')->findOrFail($id);
dd($student->contact);
// Again, can be `null` or an instance of `Contact`
The with() clause is eager loading, and doesn't do anything until you try to access $student->contact, but due to the nature of hasOne(), it can be null.

Laravel Multiple linking column in another table with relationships?

I'm trying to create a league table in Laravel but I'm running into some issues with guess what, relationships, again. They never seem to work for me in Laravel. It's like they hate me.
I have a modal for matches
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Match extends Model
{
protected $primaryKey = 'id';
protected $table = 'matches';
public $timestamps = false;
protected $guarded = ['id'];
}
And a modal for teams, but with a matches() function
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function matches() {
return $this->hasMany('App\Database\Match', 'team_one_id, team_two_id');
}
}
I think the issue comes with team_one_id, team_two_id as the teams primary key could be in either one of them columns for the other table. When calling count() on matches() it throws an error.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'matches.team_one_id, team_two_id' in 'where clause' (SQL: select count(*) as aggregate from matches where matches.team_one_id, team_two_id = 1 and matches.team_one_id, team_two_id is not null)
can you try this syntax
return $this->hasMany('modelPath', 'foreign_key', 'local_key');
Does Match table have a column maned 'team_id'?
because it's the default naming convention in the laravel docs for mapping the tables.
if you do have the column and populate the data you can just remove the foreign & local keys from matches() relationship. you don't need it. Laravel will automatically map it for you.
if you do not have the 'team_id' on Matches table please add the column and add the respective team ids for matches.
<?php
namespace App\Database;
use Illuminate\Database\Eloquent\Model;
class Team extends Model
{
protected $primaryKey = 'id';
protected $table = 'teams';
public $timestamps = false;
protected $guarded = ['id'];
public function matches() {
return $this->hasMany('App\Database\Match');
}
}
This way you can implement it, Add these relationship and a method in Team Model
public function homeMatches() {
return $this->hasMany('App\Database\Match', 'team_one_id');
}
public function awayMatches() {
return $this->hasMany('App\Database\Match', 'team_two_id');
}
public function matches() {
return $this->homeMatches->merge($this->awayMatches);
}
Now Fetch the data
$team = Team::find(1);
$matches = $team->matches(); //now it will fetch all matches for both columns
If you want to fetch matches as attributes then you can add one method
in your Team model
public function getMatchesAttribute()
{
return $this->homeMatches->merge($this->awayMatches);
}
Now you can fetch the matches as $matches = $team->matches;
Here is the difference
$team->matches returns Illuminate\Database\Eloquent\Collection
And
$team->matches() returns Illuminate\Database\Eloquent\Relations\{Relation Name}
You can't use matches in Eager loading like Team::with('matches') because matches is not a relationship and that causing your Error. What you can do is add homeMatches and awayMatches in eager loading and then call $team->matches().
$teams = Team::with('homeMatches', 'awayMatches')->get();
$teams->each(function ($team) {
print_r($team);
print_r($team->matches());
});

Laravel eager load a relationship based on the result of relationship method

I have the following entities:
User
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'members';
protected $primaryKey = 'member_id';
public function licences(){
return $this->hasMany('Licence', 'subid', 'member_id');
}
}
Licence
class Licence extends \Eloquent {
protected $table = 'licence';
protected $primaryKey = 'id';
protected $active = false;
const DATE_FORMAT = 'Y-m-d';
protected $fillable = [];
public function __construct(){
$this->checkifIsActive();
}
public function owner(){
return $this->belongsTo('User', 'member_id', 'subid');
}
public function checkifIsActive(){
if($this->start_date <= date($this->DATE_FORMAT) && $this->end_date >= date($this->DATE_FORMAT)) $this->active = true;
}
}
One user can have many licences, and the licenses that the user has may be either active or inactive - this is determined by a start and end date on the licence.
I'm trying to load a User object, and at the same time pull in their licences, but only those that are active.
Within the licence model, I am setting the 'active' variable to true, when the object is instantiated, so we have a way of knowing the status of the licence.
The code so far that I've tried is:
return User::findOrFail($id)->with('licence.active')->get();
However, this is not quite right - as there's no actual condition check done on the 'licence.active'.
How would I return a user, loaded by an ID, along with the licences they have associated that are have a boolean 'active' variable set to 'true'?
You can use eager loading constraints to query the relation like so;
$user = User::with(array('license' => function($query){
$query->where('start', '<=', Carbon::now())
$query->where('end', '>=', Carbon::now())
}))->find($id);
This will then only return the licenses that are active.
Optionally you could query the result of the relationship like so;
public function activeLicences(){
return $this->hasMany('Licence', 'subid', 'member_id')->where('start', '<=', Carbon::now())->where('end', '>=', Carbon::now());
}
Then all you would have to do is the following to get the results;
$user = User::with('activeLicenses')->find($id)
Please Note: This has not been tested.

relationship array null when eager loading in laravel

I am having issues getting the relationship array back when eager loading in laravel 4. for example:
controller:
foreach (Apps::with('extra')->get() as $app)
{
print_r($app->toArray());//returns array but my relationship array at the bottom says null
echo $app->extra; //this will show my relationship details
}
model:
class Apps extends Eloquent
{
protected $connection = 'mysql_2';
protected $table = 'apps';
public $timestamps = false;
protected $primaryKey = 'name';
public function host()
{
return $this->belongsTo('Hosts','name');
}
public function extra()
{
$this->primaryKey='app_ip';
return $this->hasone('Extra','ip');
}
//other functions below.......
}
class Extra extends Eloquent
{
protected $connection = 'mysql_3';
protected $table = 'extra';
public $timestamps = false;
protected $primaryKey = 'ip';
public function app(){
return $this->belongsTo('Apps', 'app_ip');
}
mysql:
My mysql tables were not created through laravel they were previously existent. the app_ip column in the Apps table relates to the ip column in the extra table. it is a 1 to 1 relationship and I have specified the primary key in the relationship function. I am getting relationships back so I know that it is working.
I am able to get relationship data back when I call the function directly, but it does not show the relationship data when I try and print the full array. The main goal is to be able to return both the relationship columns and the app columns in one response.
You need to do this:
$apps = Apps::all();
$apps->load('extra');
foreach ($apps as $app)
{
print_r($app->toArray()); // prints your relationship data as well
}
What you have should work and iterating through the collection or using ->load() to eager load shouldn't make a difference. Are you using the visible restriction on your models? If so you will need to include the relationships.
class Apps extends Eloquent {
protected $visible = array(
'id',
'name',
'created_at',
'extra', // Make the relationship 'visible'
);
public function extra()
{
return $this->hasMany('Extra');
}
}

Categories