Laravel: one to many relationship - php

There is such a structure:
There is a model book (Book) and model systems age restrictions (Rars).
One book can be only one rars, but on one rars can refer a lot of books. That is, the relationship - one to many?
The model Book:
class Book extends Model
{
public function rars()
{
return $this->belongsTo('App\Rars');
}
}
The model Rars:
class Rars extends Model
{
public function books()
{
return $this->hasMany('App\Book');
}
}
In migration Book:
$table->integer('rars_id');
$table->foreign('rars_id')->references('id')->on('rars');
Run code:
$book->rars()->save(\App\Rars::where('eternal_name', 'no_limits')->first());
(Rars with this eternal_name, guaranteed to exist)
And this return:
[BadMethodCallException]
Call to undefined method Illuminate\Database\Query\Builder::save()
What am I doing wrong?

According to the official documentation, for updating 'Belongs To' relationships you should use associate method.
So i think this will work:
$book->rars()->associate(\App\Rars::where('eternal_name', 'no_limits')->first());
$book->save();
For more information you can read here, https://laravel.com/docs/5.1/eloquent-relationships#inserting-related-models

Do not try to edit Rars with an Instance of Book. Make an instance of Rars instead. if you have the book id, do as following.
$book = new Book();
$book = $book->find($bookId);
$rars = new Rars();
$rars = $rars->find($book->rars_id);
/* Update data */
$rars->save();

Related

Building ternary relationship using Laravel Eloquent Relationships

Have three entities:
Project
Employee
Employment
Problem description: Employee can work on many projects and for each he has one employment. I want to have access to all projects and your referred employments of a certain employee.
I'm not sure but the relationship must look like a ternary:
The physical table is not defined yet. So, be free to design (most basic) them.
And my question:
How i can build using Laravel Eloquent Relationships?
Basically your four tables will be something like:
employee
id
...your fields
project
id
...your fields
employments
id
...your fields
employee_project
employee_id
project_id
employment_id
You can split the problem in 2 by 2 relations:
class Employee extends Model{
public function projects(){
return $this->belongsToMany("Project")
}
// Second relation is Optional in this case
public function employments(){
return $this->belongsToMany("Employment", 'employee_project')
}
}
A Project model
class Project extends Model{
public function employees(){
return $this->belongsToMany("Employee")
}
// Second relation is Optional in this case
public function employments(){
return $this->belongsToMany("Employment",'employee_project')
}
}
A Employment model
class Employment extends Model{
public function employees(){
return $this->belongsToMany("Employee")
}
public function projects(){
return $this->belongsToMany("Project")
}
}
At this point in your controller you can manage your relation, for example if you want to add to $employee, the project with id 1 with the employment with id 2 you can simply
$employee->projects()->attach([1 => ['employment_id' => '2']]);
I hope this answer to your question.
If you need timestamps in your pivot table, add ->withTimesetamps() to your relationships.
Employee has Employment
Employment has Project

Inserting one to one relationship is not working in Laravel5

I have two tables: client and payment_term. I want to save the client table while keeping a relationship with payment term.
My model classes are:
class Client extends Model {
public function payment_term() {
return $this->hasOne('App\Model\PaymentTerm');
}
}
class PaymentTerm extends Model {
public function client() {
return $this->hasOne('App\Model\client');
}
}
I need to insert client with payment.my code is given below but not working,
$client = new Client();
$client->name = Input::get('name');
$client->save();
//Payment term
$term = PaymentTerm::findOrFail(Input::get('term_id'));
$client->payment_term()->save($term);
}
Could you help me to solve the issue? I have gone through docs and some others questions, but none of them are working for me. I also want to know the best practice for inserting a related model.
Your relationships are not setup correctly. The complement to a hasOne relationship is a belongsTo relationship. Additionally, it is the model that contains the foreign key field that is on the belongsTo side.
From the code, it looks to me like you have it setup so that the client table has a term_id field (the foreign key to the payment_term record). If this is the case, your relationships should be:
class Client extends Model {
public function payment_term() {
return $this->belongsTo('App\Model\PaymentTerm', 'term_id');
}
}
class PaymentTerm extends Model {
public function client() {
return $this->hasOne('App\Model\Client', 'term_id');
}
}
You can find more on Laravel relationships in the documentation here.
Im not sure but I think your $client->save() is causing the issue.
Try using this code instead -
$client = new Client();
$client->name = Input::get('name');
//Payment term
$term = PaymentTerm::findOrFail(Input::get('term_id'));
$term->client()->save($client);
Also you might need to change App\Model\client to App\Model\Client
About best practices I think the code examples on documentation could help you out - http://laravel.com/docs/5.0/eloquent#inserting-related-models

Laravel Eloquent Join

I'm fairly new with Laravel. I'm still trying to learn it. My question is:
I have 3 tables named
games
game_options
game_platforms
I have 3 Models for those tables
Game Model
class Game extends Eloquent
{
protected $table = 'games';
public function platforms()
{
return $this->hasManyThrough('GamePlatform','GameOptions','id','game_id');
}
}
GamePlatform Model
class GamePlatform extends Eloquent
{
protected $table = 'game_platform';
}
GameOption Model
class GameOptions extends Eloquent
{
protected $table = 'game_options';
}
So when I do
$game = Game::find(1)->platforms;
It only shows,
{"id":1,"platform_id":20,"game_id":1}
{"id":1,"platform_id":21,"game_id":1}
{"id":1,"platform_id":22,"game_id":1}
{"id":1,"platform_id":23,"game_id":1}
{"id":1,"platform_id":24,"game_id":1}
But I need game name and platform names with those ID's. The thing is, I want to do this with eloquent only. I could go with "DB" or oldschool SQL but I want to learn if this way is possible or not.
Also I'm looking for better documentation/books for laravel. Most of what I read were only introduce laravel or far too advanced for me.
I left a comment earlier about this but now I'm pretty sure it's the answer you're looking for: you should use belongsToMany rather than hasManyThrough. So first, might I suggest you rename your tables and models to follow Laravel's conventions (plural snake_case table names, singular snake_case alphabetical order pivot table names, singular StudlyCaps model names), that way you'll have the following situation:
Tables:
games
id
name
game_option
id
game_id
option_id
options
id
option
name
Now you can rewrite your models to conform to the new structure, and use a belongsToMany relationship too:
class Game extends Eloquent
{
public function platforms()
{
return $this->belongsToMany('Option');
}
}
class Option extends Eloquent
{
public function platforms()
{
return $this->belongsToMany('Game');
}
}
Note: you don't have to model the pivot table (game_option) unless you store extra data on the pivot.
Now you should be good to get all options for a given game:
$options = Game::find(1)->options;
Or if you need to get all platforms (though I am trying to infer meaning of your code here regarding options and platforms):
$platforms = Game::find(1)->options()->whereOption('platform')->get();
you can use the with method with eloquent
$game = Game::where('id',1)->with('platforms')->get();
Should return you the game and platforms
For documentation I would first start with the documentation provided (find it to be about 50% complete) and with the api everything else is covered
You would have to model your tables like:
**games**
id
name
**game_options**
id
game_id
name
**game_platform**
id
game_options_id
platform_id /* which i assume you get from a platform master table */
Then in your Game Class:
class Game extends Eloquent
{
protected $table = 'games';
public function platforms()
{
return $this->hasManyThrough('GamePlatform','GameOptions','game_id','game_options_id');
}
}
Now, this would be assuming that Game Platform belongs to Games through Game Options.

Laravel Eloquent ORM relationship naming conventions

When defining an inverse relation in Eloquent, do you have to name your dynamic property the same as your related model?
class Book extends Eloquent {
public function author()
{
return $this->belongsTo('Author');
}
}
$books = Book::all()
foreach ($books as $book) {
echo $book->author->firstname;
}
In the above example, do I have to call this method author or can I name it something else? I tried to name it to something else (just out of curiosity) but it then returns null hence the errors "Trying to get property of non-object".
EDIT: I got it to work by passing the foreign key to belongsTo, like this:
class Book extends Eloquent {
public function daauthor()
{
return $this->belongsTo('Author', 'author_id');
}
}
$book = Book::find(55);
dd($book->daauthor);
Can someone explain why?
The method belongsTo tries to determine the attribute which links to the Author model. To accomplish this Laravel uses the function name of the caller.
So in your code Laravel sees the daauthor function and tries to use the attribute daauthor_id in the books table to fully your request. As your books table does not have this attribute it fails.
By setting the $foreignKey on the method you can override the default behaviour:
public function daauthor()
{
return $this->belongsTo('Author', 'author_id');
}
For more details check out the source code of \Illuminate\Database\Eloquent\Model.

Laravel attach() method not working to hasMany side

The application has the models:
Atividade.php
class Atividade extends Eloquent {
public function intervencoes() {
return $this->belongsToMany('Intervencao');
}
}
Intervencao.php
class Intervencao extends Eloquent {
public function atividades() {
return $this->hasMany('Atividade');
}
}
The following code works:
Atividade::find($id)->intervencoes()->attach($intervencao_id);
But, this...
Intervencao::find($id)->atividades()->attach($atividade_id);
Returns an BadMethodCallException:
Call to undefined method Illuminate\Database\Query\Builder::attach()
SOLUTION (thanks to #gnack):
I was trying to set a many-to-many relationship, so just needed to change this...
return $this->hasMany('Atividade');
To this:
return $this->belongsToMany('Atividade');
See the Laravel documentation here:
http://laravel.com/docs/eloquent#inserting-related-models
Basically you have set up two different types of relationships for the same two tables - you've set up a many-to-many and a one-to-many. It looks as though you probably wanted a many-to-many, so you'll need to change this line:
return $this->hasMany('Atividade');
To this:
return $this->belongsToMany('Atividade');
This will set the relationship up as a many-to-many relationship, which will then support the attach() method.
The attach() method is only for many-to-many, for other relationships there's save() or saveMany() and associate() (see the docs linked above).
See the documentation Laravel 5.7
A Comment belongTo an unique Post
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo('App\Post');
}
}
A Post can Have multiple Comments
class Post extends Model
{
/**
* Get the comments for the blog post.
*/
public function comments()
{
return $this->hasMany('App\Comment');
}
When you want to update/delete a belongsTo relationship, you may use the associate/dissociate method.
$post= App\Post::find(10);
$comment= App\Comment::find(3);
$comment->post()->associate($post); //update the model
$comment->save(); //you have to call save() method
//delete operation
$comment->post()->dissociate();
$comment->save(); //save() method
attach() is for many-to-many relationships. It seems your relationship is supposed to be a many-to-many but you have not set it up correctly for that.
class Intervencao extends Eloquent {
public function atividades() {
return $this->belongsToMany('Atividade');
}
}
Then the attach() should work
In my case I've two roles() methods that's why it's throwing this error.

Categories