Eloquent hasOne seems to be updating wrong table - laravel

I am getting an integrity constraint violation on an update to my users table when I am adding the current User to a Product. I am also using uuids instead of auto-incrementing so it adds another layer of complexity. I think I might be declaring the relationships wrong.
The error looks like it is trying to update the users table tryiSQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: users.uuid (SQL: update "users" set "uuid" = ?, "updated_at" = 2019-09-24 13:18:05 where "uuid" = 8ee98fac-11f7-5114-b9f1-772fe9732a49)
users table
uuid
User.php
public function products(){
return $this->hasMany('App\Product', 'user_uuid', 'uuid');
}
products table
uuid
user_uuid
Product.php
class Product extends Model
{
use SoftDeletes;
use uuidTrait;
protected $primaryKey = 'uuid';
public $incrementing = FALSE;
public function user(){
return $this->hasOne('App\User', 'uuid', 'user_uuid');
}
public static function boot(){
parent::boot();
static::creating(function(Product $instance){
$instance->user()->save(auth()->user());
});
}
}

You need the uuid of the current user
static::creating(function(Product $instance){
if(empty($instance->uuid)){
$instance->uuid = auth()->user()->user_uuid;
}
});
or you use the associate function
$product = new Product;
//...
$product->save();
$user = User::find(Auth::user()->id);
$user->associate($product);
$user->save();

Related

Laravel hasMany to a composite table return empty array

I have 3 tables that connected each other
account_receivables
account_receivable_id (PK)
...
account_receivable_details
account_receivable_id (PK FK)
order_id (PK FK)
orders
order_id (PK)
...
After that, I want to make a relationship like this
class AccountReceivable extends Model
{
protected $fillable = [
'account_receivable_id','event_id','account_receivable_date','account_receivable_description','account_receivable_amount','xendit_id','xendit_status', 'xendit_expiry_date','account_receivable_percentage'
];
protected $primaryKey = 'account_receivable_id';
public $incrementing = false;
public function accountReceivableDetail()
{
return $this->hasMany(AccountReceivableDetail::class, 'account_receivable_id', 'account_receivable_id');
}
}
But when I called AccountReceivable like this it returns an empty array of accountReceivableDetail
public function getRiwayatById(Request $request, $id){
$riwayat = AccountReceivable::where([
'account_receivable_id' => $id
])->with('accountReceivableDetail')->first();
return $riwayat;
}
Do you know why it returning an empty array when I actually have data in the table?
You are passing owner key wrong Corrected function is:
public function accountReceivableDetail()
{
return $this->hasMany(AccountReceivableDetail::class, 'account_receivable_id', 'id');
}
If account_receivables table and account_receivable_details table both have one to one relation then you should replace hasMany() to hasOne()

Eloquent 'with()' returns null

I have a simple relationship between two models: User and Prescription. A user has many prescriptions. In the PrescriptionsController, when I try to get the user that the prescriptions belongs to, it returns null when using with().
PrescriptionsController
public function index()
{
$user_id = Auth::id();
$prescriptions = Prescription::with('user')->where('prescription_for', $user_id)->get();
return response()->json($prescriptions);
}
The result from that Eloquent query:
[{"id":1,"prescription_for":1,"prescription_by":1,"prescription_content":"Paracetamol 120mg - O cutie. Mod administrare: 1 Dimineata | 0 Pranz | 0 Seara","created_at":"2020-10-13T17:33:35.000000Z","updated_at":null,"user":null}]
You can see that the last parameter is null.
In my User model, I have set up the relationship using:
public function prescriptions()
{
return $this->hasMany(Prescription::class);
}
And the Prescription model:
protected $table = 'prescriptions';
public $primaryKey = 'id';
public $timestamps = true;
public function user()
{
return $this->belongsTo(User::class);
}
I am using VueJs so I cannot just do $prescription->user->name as you can in Blade files, that's why I need to eager load the data.
The way I set up the Prescriptions table:
$table->id();
$table->unsignedBigInteger('prescription_for');
$table->foreign('prescription_for')->references('id')->on('users');
$table->unsignedBigInteger('prescription_by');
$table->foreign('prescription_by')->references('id')->on('users');
$table->string('prescription_content');
$table->timestamps();
Any ideas to why this happens? Thanks!
On your prescriptions table, your primary key is prescription_for. If the parent model does not use id as its primary key, or you wish to find the associated model using a different column, you may pass a third argument to the belongsTo() method specifying the parent table's custom key :
public function user()
{
return $this->belongsTo(User::class, 'id', 'prescription_for');
}

How to properly implement this polymorphic relationship in Laravel?

I am trying to build an inventory for users in Laravel 5.8, however the items have their own properties, therefore I needed to set up a polymorphic relationship. When attaching items to users, it tries to add the model User to the table on itemable_type and the user's ID to itemable_id aswell as add the User's ID to user_id, something I could workaround by passing the models I need, but when I try to retrieve them it tries to find item with itemable_type = 'App\Models\User', which makes me think something's completely wrong here. Can I have some orientation on how to solve it?
class User extends Model
{
public function inventory()
{
return $this->morhpToMany(InventoryItem::class, 'itemable', 'user_inventories', null, 'itemable_id')
->withPivot('amount', 'notes');
}
}
class InventoryItem extends Model
{
public $timestamps = false;
protected $table = 'character_inventories';
protected $fillable = [
'character_id', 'itemable_type', 'amount', 'parent_id', 'notes'
];
public function cloth()
{
return $this->mophedByMany(Cloth::class, 'itemable');
}
public function food()
{
return $this->morphedByMany(Food::class, 'itemable');
}
// Other similar relations
}
// The Inventory migration:
Schema::create('user_inventories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedInteger('itemable_id');
$table->string('itemable_type');
$table->unsignedInteger('amount')->default(0);
$table->text('notes', 65535)->nullable();
$table->foreign('character_id')->references('id')->on('characters');
});
The expected result is the User model to have different items in his inventory, but the relation is trying to query by joinning to itself and filtering by user type instead of actual items.
The error:
Syntax error or access violation: 1066 Not unique table/alias: 'user_inventories' (SQL:
select `user_inventories`.*,
`user_inventories`.`itemable_id` as `pivot_itemable_id`,
`user_inventories`.`itemable_type` as `pivot_itemable_type`,
`user_inventories`.`amount` as `pivot_amount`,
`user_inventories`.`parent_id` as `pivot_parent_id`,
`user_inventories`.`notes` as `pivot_notes`
from `user_inventories`
inner join `user_inventories` on `user_inventories`.`id` = `user_inventories`.`itemable_id`
where `user_inventories`.`itemable_id` in (4)
and `user_inventories`.`itemable_type` = App\Models\User)
I highly suspect that you have to references the user table in the inventory relation. In general it is a million times easier just following the Laravel convention for naming.
public function inventory()
{
return $this->morhpToMany(InventoryItem::class, 'itemable', 'users', null, 'itemable_id')
->withPivot('amount', 'notes');
}

Laravel 5.3 belongsToMany return null, pivot data

I have a next models:
class Product extends Model{
protected $table = 'products';
public function payments()
{
return $this->belongsToMany('App\Payment', 'payment_product', 'product_id', 'payment_id')
}
}
class Payment extends Model{
protected $table = 'payments';
public function products(){
return $this->belongsToMany('App\Product');
}
}
Pivot table: payment_product(id, product_id, payment_id)
Eloquent
public function details($id){
$product = Product::with('payments')->find($id);
dd($product->payments); // return null
return view('products.details', ['product' => $product]);
}
I need to bring in a foreach, but $product->payments is null. Why is that ?
All the tables are not empty.
UPD
Sub query $this->belongsToMany('App\Payment', 'payment_product', 'product_id', 'payment_id');
Results:
try:
public function payments()
{
return $this->belongsToMany('App\Payment', 'payment_product', 'payment_id', 'product_id')
}
I think you have your FK in the wrong order.
In fact, I don't think you need to specify anything more than:
public function payments()
{
return $this->belongsToMany('App\Payment')
}
Looks like you are joining two tables based on unrelated fields.
When you do
return $this->belongsToMany('App\Payment', 'payment_product', 'product_id', 'payment_id')
your table products gets inner joined with payment_product on
products.product_id = payment_product.payment_id.
But I think these two columns are not the related keys. Instead, in your payment_product, join with the product_id in this table with products.product_id.
That might work.
Rename payments to payments_method:
public function payments_method(){
return $this->belongsToMany('App\Payment'); //or ('App\Payment', 'payment_product', 'payment_id', 'product_id')
}
$product = Product::find($id);
$product->payments_method; //this is work
This is magic:)

Get incorrect table when tried to insert

I have a bizarre problem with my insert. So my migration is :
class CreatePhotoCategoryTable extends Migration {
public function up()
{
Schema::create('photo_category',function($table){
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::drop('photo_category');
}
}
My Model :
class PhotoCategory extends Eloquent {
protected $fillable = array('name');
public static $rules = array(
'name' => 'required',
);
}
And my controller:
class PhotoCategory extends BaseController{
public function getAddPage(){
return View::make('admin.photo_category.addPhotoCategory');
}
public function postCreate(){
$validator = Validator::make(Input::all(), \PhotoCategory::$rules);
if($validator->passes()){
$oPhotoCategory = new \PhotoCategory();
$oPhotoCategory->name = Input::get('name');
$oPhotoCategory->save();
$iLastId = $oPhotoCategory->id;
return Redirect::to('/administration/category_photo/edit/'.$iLastId)
->with('message_succes','Succes');
}
return Redirect::to('/administration/category_photo/add')
->with('message_error','Error')
->withErrors($validator)
->withInput();
}
Evident my table in database is called photo_category but when I tried to save into this table I get en sql error :
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'photo_categories' doesn't exist. So why my save() method get table photo_categories instead of photo_category. Please help me.
The naming convention for database tables in Laravel is plural. So Laravel assumes from your model name PhotoCategory that your table is called photo_categories. You have two options:
Change the name of your table to photo_categories
Specify the table name in your model by adding:
protected $table = 'photo_category';
Make sure you name your controllers with different names from your models, as this might bring you some issues since both are classes and both have the same name.
And also your Model class represents your database table so you need to specify your table name as
protected $table = 'photo_category';

Resources