I have this situation where I want (hope/wish) to use a particular number e.g 1 directly as second parameter instead of using user_id. I was wondering if there was a to achieve this? or is it just not possible?
For example, currently I have relationship like this.
class orders extends Model
{
protected $tableName = 'orders';
protected $primarykey = 'id';
protected $fillable = [
'user_id',
'qty',
.
.
];
public function user()
{
return $this->belongsTo('App\User', user_id)->withDefault(['name' => 'N/A']);
}
But I was hoping if there was some way I can add another relationship like this?
public function main_user()
{
return $this->belongsTo('App\SpecialUser', 1)->withDefault(['name' => 'N/A']);
}
As can be see there is no column in this table that references SpecialUser table. However, I want a specific user to be accessed on that table using relationship.
I hope I am clear enough and sorry in advance for my newb way of explaining it because I am one.
Thanks in advance.
Please, try this code :
public function mainUser()
{
return $this->belongsTo('App\SpecialUser');
}
public function mainUserOne()
{
return $this->mainUser()->where('id', 1);
}
Controller :
Use App\Order;
$mainUser = (new Order)->mainUserOne()->first();
Related
I have 3 way relationship firstl i have get code like this in a controller
Trial::with('subjects')->where('source_id', $sourceId)->get()->toArray()
Now I want to sort subject.reactions on desc order of subject.reactions.accounts.nb_followers column. I tried to use orderby on relationship but it does not work because it sorting account indsted on reactions. I want to sort reaction based on value of "nb_followes" column present inside account table.
Trail Model
class Trial extends Model
{
use HasFactory;
public $table = 'trials';
public function subjects()
{
return $this->hasMany(Subject::class, 'trial_id')->with(['reactions', 'news'])->withCount('reactions');
}
}
Subject Model
class Subject extends Model
{
use HasFactory;
public $table = 'subjects';
public function reactions()
{
return $this->hasMany(Reaction::class, 'subject_id', 'id')->with(['accounts' => function ($q) {$q->orderBy('nb_followers', 'DESC');}])->where('twitter_error', 0)->where('active', 1)->orderby('key_reaction', 'DESC');
}
public function news()
{
return $this->hasone(News::class, 'id', 'news_item_id');
}
Reaction Model
class Reaction extends Model
{
use HasFactory;
public $table = 'reactions';
public function accounts()
{
return $this->belongsTo(Account::class, 'account_id', 'id')->where('name', '!=', '');
}
Thank you in Advance.
I want to sort reactions based on account table's column yes i cant use simple eloquent query because it will not create a structure that i want so that's why i created these relationships.
first you need to loop over trails using map method
second you need to use transform method to transform your subject in
sorted manner
as show in Subject model you need sort reaction by key_reaction
feild
$trails = ViewTrial::with('subjects')->where('source_id', $sourceId)->get();
$trails->map(function($trails){
return $trails->subjects = $trails->subjects->transform(function (&$subject) {
return [
"column" => $subject->column,
"reactions" => $subject->reactions->sortByDesc(function ($reactions) {
return $reactions['accounts']['nb_followers'];
})->sortByDesc('key_reaction')->values()->all()
]
})->values();
});
return $trails->toArray();
I have setup my model as following:
class Items extends Model {
use HasFactory;
protected $table = 'item';
protected $primaryKey = 'id';
protected $connection = 'mysql';
public $timestamps = false;
protected $fillable = ['user_id', 'title', 'desc', 'start_datetime', 'due_datetime', 'priority', 'status'];
public function getManager() {
return $this->belongsTo(User::class, 'user_id');
}
public function getAssignees() {
return $this->belongsToMany(User::class);
}
}
I am getting all items using the controller method below, what I want to do is to populate the user_id field in each of the items using getManager() method I declared in my Item model. I know how to do this when getting only one item, but how to populate every record when getting all of them?
public function getall() {
try {
$items = Item::get();
return response()->json(['items' => $items], 200);
} catch (Throwable $err) {
return response()->json($err, 400);
}
}
I have tried this but no luck:
public function getall() {
try {
$items = Item::get();
$items = array_map(function ($el) {
return $el->manager = $el->getManager()->get();
}, $items);
return response()->json(['items' => $items], 200);
} catch (Throwable $err) {
return response()->json($err, 400);
}
}
There are a few things here that I have some concerns about. Your code may work, but you are also doing more than you need to and not using Laravel how it was meant to be used.
Model Name
Your model name is Items, but it should be singular, Item. This helps Laravel automate things so you have less work to do.
https://laravel.com/docs/8.x/eloquent#eloquent-model-conventions
class Item extends Model {
Database Settings
You've set the $table, $primaryKey, and $connection attributes, but these should be automatic. You can probably remove them.
protected $table = 'items'; // assuming your model name is Item, this would automatically be 'items'
protected $primaryKey = 'id'; // default is already 'id'
protected $connection = 'mysql'; // default is your main db, probably already 'mysql', unless if you have multiple db connections
Timestamps
I'm not sure why you'd want to turn timestamps off. You definitely can but I always find it helpful to know when something was created or last updated. Since Laravel handles the timestamps for you, I'd suggest leaving it on, but it's up to you.
https://laravel.com/docs/8.x/eloquent#timestamps
public $timestamps = false;
Manager Relationship
Your manager relationship is getManager but should just be manager. It will still work, but isn't how Laravel was meant to work. I would suggest changing it to manager(), and not specifying the column name. This would make the column name automatically manager_id, so you'd have to update that. Or you can keep the column name 'user_id'.
https://laravel.com/docs/8.x/eloquent-relationships#one-to-many-inverse
public function manager() {
return $this->belongsTo(User::class);
}
Assignees Relationship
Same as with the Manager relationship, you should change getAssignees() to assignees(). I'm assuming you already have a database migration set up for your 'item_user' table that Laravel will look for. If not, check the Laravel docs on how to set it up.
https://laravel.com/docs/8.x/eloquent-relationships#many-to-many
public function assignees() {
return $this->belongsToMany(User::class);
}
Retrieving Items
Finally, with the above changes, getting all Items should be easy. To load the relationships, use the $with method. This is called Eager Loading. Check the docs for more info.
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading
$items = Item::with('manager','assignees')->get();
Returning Response Codes
You were returning your responses incorrectly. You do not need to set the response code 200, as this is the default. If you are going to set it to something else, put the code in the response() method, instead of the json() method.
https://laravel.com/docs/8.x/responses
return response()->json(['items' => $items]);
return response($err,400);
Now putting it all together, your Item model should look something like this:
class Item extends Model {
use HasFactory;
protected $fillable = ['manager_id', 'title', 'desc', 'start_datetime', 'due_datetime', 'priority', 'status'];
public function manager() {
return $this->belongsTo(User::class);
}
public function assignees() {
return $this->belongsToMany(User::class);
}
}
public function getall() {
try {
$items = Item::get()
->transform(function($el){
$el->manager = $el->getManager()->get();
);
return response()->json(['items' => $items], 200);
} catch (Throwable $err) {
return response()->json($err, 400);
}
}
Try the transform method on your results and it would work.
https://laravel.com/docs/8.x/collections#method-transform
the transform function would basically just iterate over the results and do whatever it is told to like a for loop but for collections.
Also, to make your query efficient avoid the use of loading the relation in the transform function and and use with function of laravel to make it efficient
EDITED: Guys can you review your suggested duplicate? I did some research before I ask this question, and I'm already to that link, that is not the answer that I'm looking for.
How can I pluck specific column in eloquent relationship? I want only name column to be returned when I Student::find()->subject;
I tried the below codes but doesn't work and returns me an error
App\Student::subject must return a relationship instance.
class Student extends Model
{
protected $table = 'subjects';
protected $fillables = ['id', 'name', 'gender', 'birthdate', etc.];
public function subject()
{
return $this->hasMany('App\Subject')->pluck('name');
}
}
You can use any query builder functions on the relation.
Use select to only select the name column
public function subject()
{
return $this->hasMany('App\Subject')->select('name');
}
Here is where I save the game:
public function storeGame() {
$player = new Player(['player_name' => Request::get('host_name')]);
$player->save();
$game = new Game(Request::all());
$game->host_id = $player->id;
$game->save();
$player->game_id = $game->id;
$player->save();
return redirect('lobby');
}
Here is the eloquent relationship:
class Game extends Model {
protected $table = 'games';
protected $fillable = ['game_name','password','round_time','num_rounds','num_players','roles_bool'];
protected $hidden = ['password'];
public function host() {
return $this->hasOne('App\Player', 'id');
}
public function players() {
return $this->hasMany('App\Player', 'id');
}
}
The problem is when I save the game, the value of the host id is changing. These are the results of a var_dump() after saving.
$game->host_id:
int 2
$game->host->id:
string '1' (length=1)
Why is this happening and how do I stop it?
Thanks for help in advance.
Duncan - I'm thinking this has something to do with your Host relationship. I don't see a host_id anywhere in your fillable fields on your Games model.
You should have a host_id fillable field on your Games model and then the relationship would look like this:
public function host() {
return $this->hasOne('App\Player', 'host_id');
}
You probably loaded related host object before and it hasn't been "refreshed" after you changed host id. Actually you shouldn't change relations ids directly, there are dedicated methods to do that: http://laravel.com/docs/4.2/eloquent#inserting-related-models
I'm trying out this model-thing, but I can't really get my grasp of it.
For the moment I have two tables (companies and sellers) "companies" as a column named "cResponsibleID" which I want to map to "sID" in "sellers".
models/Companies.php
class Companies extends Eloquent {
protected $table = 'companies';
protected $primaryKey = 'cID';
public function sellers() {
return $this->belongsTo('Sellers','sID');
}
}
models/Sellers.php
class Sellers extends Eloquent {
protected $table = 'sellers';
protected $primaryKey = 'sID';
public function companies() {
return $this->hasMany('Companies','cResponsibleID');
}
}
I then want to do something like Companies::with('sellers.sName')->get() to "translate" cResponsibleID to sName.
Maybe I'm all out wrong.
Thankful for all help.
Can you try printing the result of:
<?php
$company = Companies::with('sellers')->get();
echo '<pre>';
print_r($company->sellers);
And see how they're build up, I blieve the sellers.ANYTHING construction is only meant for multiple nested relations.
for example of a Seller has an Address as a relation, it would be Companies::with('sellers.address')