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
Related
I am trying to return data from my database and I want it to include data from the related table. It is a one-to-many relationship. However I all I get is an error
Property [User] does not exist on this collection instance.
In my User model I have
//App\User.php
class User extends Authenticatable{
use Notifiable;
public function systems(){
return $this->hasMany(\App\Models\General\systems::class,'added_by','id');
}
The other model, called systems I have
//App\Models\General\systems.php
class systems extends Model
{
public function User(){
return $this->belongsTo(\App\User::class,'added_by','id');
}
In my controller I have
$this->systemsObject = new \App\Model\General\systems();
$systems = $this->systemsObject->get()->User;
according to the Laravel Documentation this should work but it isn't. I tried reversing the foreign key/local key parameters. I made the ->User uppercase, lowercase.
I have no idea what I am doing wrong
You need to iterate over the collection, for example:
$systems = $this->systemsObject->get();
foreach ($systems as $system) {
echo $system->User->name;
}
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();
I'm starting to develop an SaaS application and I have created my database structure. I'm planning to create a middleware file which handles the database connection for that request. Within this middleware file I want to create a model which will always select only rows from any table that corresponds to the current connection cust_id (foreign key).
For example:
$Customers->where('cust_id', $cust_id)->first();
How can I do this without having to specify where('cust_id', $cust_id) in every select statement?
You can easily achieve that using Eloquent's global query scopes in your models. You can read more about them here: http://laravel.com/docs/5.1/eloquent#query-scopes
First, you need to define the Multitenant scope class, that will update all the queries that run and add the constraint on cust_id field:
class MultitenantScope implements ScopeInterface
{
public function apply(Builder $builder, Model $model)
{
if (Auth::id()) {
$builder->whereCustId(Auth::id());
} else {
$model = $builder->getModel();
// apply a constraint that will never be true
// so that no records are fetched for unauthorized users
$builder->whereNull($model->getKeyName());
}
}
public function remove(Builder $builder, Model $model)
{
$query = $builder->getQuery();
$query->wheres = collect($query->wheres)->reject(function ($where) {
return ($where['column'] == 'cust_id');
})->values()->all();
}
}
Then you need a trait that you will add to the models that need to be filtered:
trait MultitenantTrait
{
public static function bootMultitenantTrait()
{
static::addGlobalScope(new MultitenantScope());
}
public static function allTenants()
{
return (new static())->newQueryWithoutScope(new MultitenantScope());
}
}
The last piece is adding the MultitenantTrait to your model:
class SomeModel extends Eloquent {
use MultitenantTrait;
}
Now, every time you do any query using Eloquent's model methods, the cust_id constraint will be applied to the query and only models that belong to given cust_id will be available.
If for some reason you'll need to access all objects, you can use allTenants() method to run the query without the additional constraint:
$allRows = SomeModel::allTenants()->get();
Please keep in mind that I haven't tested that exact code, so let me know if you see any issues and I'll be more than happy to get that working for you :)
I'm having some trouble while saving a polymorphic one-to-one relation with Laravel 4, this is my model:
namespace App\Models\Proveedores;
class Proveedor extends \Eloquent {
public function proveedorable () {
return $this->morphTo('proveedorable', 'proveedorable_type', 'proveedorable_id');
}
And this is the specific model:
namespace App\Models\Proveedores;
class ProveedorTerminacion extends \Eloquent {
public function proveedor () {
return $this->morphOne ('App\Models\Proveedores\Proveedor', 'proveedorable', 'proveedorable_type', 'proveedorable_id');
}
This way I'm trying to save a Proveedor associated with a specific ProveedorTerminacion model, but for some reason a row for ProveedorTerminacion is created in my table, but not for Proveedor and Laravel won't show any error and return an empty response, what's wrong?
$terminador = ProveedorTerminacion::create (Input::all());
$proveedor = new Proveedor;
$proveedor->fill (Input::all());
$proveedor->proveedorable()->associate ($terminador);
$proveedor->save ();
Associate method doesn't work correctly with morphTo, as it is never setting morphable_type, so don't use it. I'm pretty sure your code should throw fatal error because of that by the way. It requires bugfix.
Instead invert creating the relation and do it in the context of morphable object:
$terminador = ProveedorTerminacion::create (Input::all());
$proveedor = new Proveedor;
$proveedor->fill (Input::all());
$terminador->proveedor()->save($proveedor);
I'm fixing that and going to send a PR to the laravel repo after some testing. I'll update my answer when it's done.
Here it is: https://github.com/laravel/framework/pull/4249
Really sorry to bother you all, but I have a noob question concerning some code in a Laravel 4 Tutorial:
In this tutorial, we have to manage relationships between multiple tables.
Here is the models codes:
<?php
class Auteur extends Eloquent
{
public $timestamps = false;
public function livres()
{
return $this ->hasMany('Livre');
}
}
The other model:
<?php
class Livre extends Eloquent
{
public $timestamps = false;
public function auteur()
{
return $this ->belongsTo('Auteur');
}
}
And when I call :
Route::any('DynEloquent',function()
{
foreach(Livre::with('auteur')->get() as $livre)
echo '"'.$livre->titre.'" a été écrit par '.$livre->auteur->nom.'<br>';
});
I have an ErrorException:Trying to get property of non-object apparently on $livre->auteur->nom.
Any help will be much appreciated since I've already tried to find my way in the official docs and other stuff like the similar questions on eloquent relationship. (even if I'm pretty sure I'm missing an easy thing)(Forgive my English since I'm french.)
Thanks.
Table auteurs:
-id
-nom
-prenom
-naissance
Table livres:
-id
-titre
-auteur_id
It looks like that your relation $livre->auteur is not returning any data, it's probably null, which is not an object and then you get the message Trying to get property of non-object. To be sure you can do:
Route::any('DynEloquent',function()
{
foreach(Livre::with('auteur')->get() as $livre)
{
dd( $livre->auteur );
}
});
You have to check tour relations, if they are really pointed to the correct $tables and your database table, to see if they are correctly filled with proper relational data.