Disable eager relations - laravel

In my project I have many Eloquent models that have eager relations configured in class like this:
protected $with = [ 'countries', 'roles' ];
But sometimes I need just old plain model without any relations. Can I somehow do:
Model::noRelations()->all()
Really don't wanna use query builder nor create another class just for few occasions.

If you have to set the $with property on your model rather than leaving it empty, you can manually override the relationships that need to be eager loaded like this:
Model::setEagerLoads([])->get();
Link to API for setEagerLoads

In addition to Thomas Kim answer.
If you anyway extend Eloquent\Model class and often need to strip off relations from model, this solution might suit you well.
Create scope in your default model class:
public function scopeNoEagerLoads($query){
return $query->setEagerLoads([]);
}
For any ORM, that extends that class you will be able to:
User::noEagerLoads()->all()

Just like the issues say
Model::without(['countries', 'roles' ])->all();

Related

How do I use a Laravel dynamic relationship?

I am a newbe in Laravel. The docs show how to use relationships like this:
One To Many (Inverse) / Belongs To
Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a hasMany relationship, define a relationship method on the child model which calls the belongsTo method:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo(Post::class);
}
}
Once the relationship has been defined, we can retrieve a comment's parent post by accessing the post "dynamic relationship property":
use App\Models\Comment;
$comment = Comment::find(1);
return $comment->post->title;
My question is: Where is this code? In a controller or in a view?
If you use MVC structure, you should understand that
Model is layer where you store your data
View is layer where you should only display your data
and Controller is layer where you can keep your logic.
If you have a lot of difficult logic or big application, you should better to use Services, as layer between Controllers And Models.
Receiving Comments from model and prepeare them should be in controller level. In view level you just define how to show them to user.
I hope it will help you to understand difference between logic layers.
you can access this relationship in controller or view like this-
suppose you want to make relation between product model and brand model:-
in product model:-
public function brand(){
return $this->belongsTo('App\Model\Brand','brand_id','id');
}
now you are able to see which product belongs to which brand without any query or using loop.
just do in controller:-
$product=Product::with('brand')->get();
here you get all the data...
and when you use it on **view **just do it:
{{$product->brand->brand_name}}
//brand name should the column name
I hope you understood...
Happy Learning!

How can I eager load a group of relations that was previously specified within model in Laravel?

I have multiple cards that belong to the user model. Like vendor, customer and admin and so on. I can eager load them typically like:
User::with(['admin', 'vendor', 'customer'])->get();
but this cards are changeable, there could be added some more. In that case I don't want to make that change everywhere where I used to eager load that group. Instead I want something like
User::withCards()->get();
And in model itself something like:
protected $cards = ['admin','vendor', 'customer'];
public function withCards(){
return $this->with($this->cards);
}
Well I tried that without luck. But I think with the example above you understand what I meaning. How could I accomplish something like that?
You are looking for local query scopes. You can achieve this using:
protected $cards = ['admin','vendor', 'customer'];
public function scopeWithCards($query){
return $query->with($this->cards);
}

Laravel Eloquent getting all 'with' relationship without specifying one by one

My relationships is something like:
player
sub
something
sub-2
sub-3
something
foobar
sub-4
I can get player by id with its sub like this:
Player::with('sub.something','sub-2','sub-3.something.foobar','sub-4')->find($id);
However I had to specify each 'with' relationship manually.
Is it possible to just get everything on the child relationship (hasMany/hasOne) in one query?
Something like:
Player::with(everything())->find($id);
The short answer is no, relationships are expensive to get so you need to be explicit with what you need to load each time. You can however specify which relationships are always eager loaded on the model:
class Player extends Model {
protected $with = [ 'sub.something','sub-2','sub-3.something.foobar','sub-4' ];
// Rest of model
}
This way you won't need to specify ::with every time when loading a model.
Yes You can use Eager Loading to get the model with related data:
eager-loading
Try this:
Player::with(['sub'])->find($id);
it will return all subs of a player.

Laravel Method [hasMany] does not exist

I have 2 controllers and models:
User Controller & Model
Hero Controller & Model
Each user can have unlimited heroes - it means that the relationship between them is one to many.
In my UserController I created the following method:
/**
* Get the heroes of the user.
*/
public function heroes()
{
return $this->hasMany(Hero::Class);
}
while in my HeroController I created this method:
/**
* Get the user that owns the hero.
*/
public function user()
{
return $this->belongsTo(User::class)
}
Added this to my routes file:
Route::get('userHeroes', 'UserController#heroes');
and it returns this error:
{"error":{"message":"Method [hasMany] does not exist.","status_code":500}}
What could have gone wrong.. ?
The controller is just a delegate between the request and the return data - you tell it that you want something, it figures out what you want, and then it calls the appropriate places to get something to return.
The hasMany() and belongsTo() methods, on the other hand, are logic specifically related to the Hero and User models, on the other hand.
What you need is to move the heroes() method to your User model, because a user can have many heroes. Also need the user() method to your Hero model, because a hero belongs to a user.
Then you put an action call in a controller. Let's say, for instance, that you have a UserController which has an getHeroes() method. That might look like this:
public function getHeroes() {
$user = auth()->user();
$heroes = $user->heroes;
return $heroes;
}
And that will format it to JSON. Just an example.
But you might want to read a tutorial or two about this, since it's fairly basic stuff and it's good to get a good handle on early on. Please don't take that the wrong way - we're happy to help if you run into problems, I just think you might need a stronger foundation. The screencasts at Laracasts are highly recommended for this purpose.
it must be declared in models, not in controllers, hasMany() is a method in eloquent models.
hasMany and belongsTo methods are eloquent class methods.
And we inherit eloquent in our model so that we can use the eloquent methods functionality.
In order to use the relation, you have to define the relation method in respective model class and then you can call from controller.
Please refer the documentation Eloquent relationship documentation
Hope i have cleared your doubt.
Thanks

Why protect tables and fields on top of every model?

I have seen a CodeIgniter application where the coder always protected table and fields at the tp of every model. Why would you do this? and maybe also why would you protect primary key separate from other fields?
class Students_model extends MY_Model{
protected $table = 'students';
protected $primary_key = 'id';
protected $columns = array(
'student_code' => array('Code', 'trim|required'),
'student_name' => array('Name', 'trim|required'),
'country' => array('Country', 'trim|required'),
);
}
This is a really good question for understanding best practices in MVC (not just Codeigniter). There are actually a few different things going on here.
1) "protected" is prolly done out of habit. This protected is the php class keyword, and has nothing to do with CI or Models. You can read about it here: http://jp2.php.net/protected; if after reading you don't understand why it is used in this case, it's because there really isn't a reason to use it in this case.
2) The key to understanding the rest is "extends MY_Model". MY_Model is a base model object where all your normal CRUD functions and utilities are written; we then inherit from it. However, our MY_Model will have a function like get_all() which will say:
$this->db->from($this->table)->get();
for example. So, in our Students model we set $this->table = "students", then the above code translates to:
$this->db->from('students')->get();
but any other models can pass a different table name. So we are able to make very simple table specific models and share all the more complex logic via MY_Model
You can see that going back to #1, it is unlikely we'll ever inherit from Students_model, so protected isn't harming anything, but isn't terribly necessary
3) $columns in this case are the validation rules; whichever MY_Model being used here is also adding the validation functions to the MY_Model instead of putting on the controllers

Resources