Call to undefined method Illuminate\Database\Eloquent\Relations\BelongsTo::save() - laravel

I want to insert data into multiple tables (one to one), but i get error and in my database the column "metode_id" is null. i want the "metode_id" is not null
this is class "Transaksi" :
class Transaksi extends Model
{
protected $table = "transaksi";
protected $primarykey = "id";
protected $fillable = ['stok_kedelai', 'stok_ragi', 'harga_kedelai', 'harga_ragi'];
public function metode()
{
return $this->belongsTo('App\Metode');
}
public function pengguna()
{
return $this->belongsTo('App\Pengguna');
}
}
This is class "Metode" :
class Metode extends Model
{
protected $table = "metode";
protected $primarykey = "id";
protected $fillable = ['bni', 'bri', 'mandiri', 'bca', 'btpn', 'ovo', 'gopay', 'dana'];
public function transaksi()
{
return $this->hasOne('App\Transaksi', 'metode_id');
}
}
This is database of "Transaksi" :
public function up()
{
Schema::create('transaksi', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('pengguna_id')->unsigned();
$table->integer('stok_kedelai');
$table->integer('stok_ragi');
$table->integer('harga_kedelai');
$table->integer('harga_ragi');
$table->bigInteger('metode_id')->unsigned();
$table->timestamps();
});
Schema::table('transaksi', function (Blueprint $table) {
$table->foreign('pengguna_id')->references('id')->on('pengguna')->onDelete('cascade')->onUpdate('cascade');
});
Schema::table('transaksi', function (Blueprint $table) {
$table->foreign('metode_id')->references('id')->on('metode')->onDelete('cascade')->onUpdate('cascade');
});
}
This is database of "Metode" :
public function up()
{
Schema::create('metode', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('bni')->nullable();
$table->integer('bri')->nullable();
$table->integer('mandiri')->nullable();
$table->integer('bca')->nullable();
$table->integer('btpn')->nullable();
$table->integer('ovo')->nullable();
$table->integer('gopay')->nullable();
$table->integer('dana')->nullable();
$table->timestamps();
});
}
i want insert data into mutiple table that which depends on the "id" of pengguna table but i get error Call to undefined method Illuminate\Database\Eloquent\Relations\BelongsTo::save()
public function data_penjualan(Request $request)
{
$pengguna = Pengguna::where('id', Auth::user()->id)->first();
$transaksi = new Transaksi();
$transaksi->stok_kedelai = $request->stok_kedelai;
$transaksi->stok_ragi = $request->stok_ragi;
$transaksi->harga_kedelai = $request->harga_kedelai;
$transaksi->harga_ragi = $request->harga_ragi;
$pengguna->transaksi()->save($transaksi);
$metode = new Metode();
$metode->bni = $request->bni;
$transaksi->metode()->save($metode);
return view('transaksi.supplier', compact('transaksi'));
}
this is my database, the "metode_id" get null, how i want that "metode_id" is not null :
enter image description here

If you try to update a belongsTo relationship, you have to use the associate method instead of save method.
...
$metode = new Metode();
$metode->bni = $request->bni;
$metode->save();
$transaksi->metode()->associate($metode);
$transaksi->save();
...

If you try to SaveMethod in the belongsTo relationship.
Add Comment(controller file)
public function addComment($id)
{
$comment = new Comment(['comment' =>'Comment 1']);
$user = User::find(1);
$user->comment()->save($comment);
return "Comment Submitted";
}
Comment.php (Model File)
class Comment extends Model
{
use HasFactory;
protected $table ="comments";
protected $fillable = ['comment'];
public function User()
{
return $this->belongsTo(User::class);
}
}
web.php (Route File)
Route::get('comment/{id}',[UserController::class,'addComment']);

Related

Deleted_by is not changing while i delete a data using observers;

I want to have fields created_by,updated_by and deleted_by and want to update these fields automatically. created_by,updated_by is working but deleted_by is not working.i am using an observer to perform this task. When i use dd($model) in deleting function in observer it shows the collection or values but the deleted_by is not updating.
My model
namespace App\Model;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Observers\UserIdFinderObserver;
class supplier extends Model
{
use SoftDeletes;
protected $fillable = [
'name', 'address', 'contact','contact_person_name','country','email'
];
public static function boot()
{
parent::boot();
$class = get_called_class();
$class::observe(new UserIdFinderObserver());
}
}
my migration file
public function up()
{
Schema::create('suppliers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('contact_person_name');
$table->string('country')->nullable();
$table->text('address')->nullable();
$table->string('contact')->nullable();
$table->string('email')->nullable();
$table->string('created_by')->nullable();
$table->string('updated_by')->nullable();
$table->string('deleted_by')->nullable();
$table->softDeletes();
$table->timestamps();
});
}
My delete function in controller
public function destroy(supplier $supplier)
{
try{
$supplier->delete();
return redirect()->route('supplier.index')->with('success', 'Supplier is deleted successfully');
}catch(Exception $e){
return redirect()->back()->withErrors($e->getMessage());
}
}
My Observer
namespace App\Observers;
class UserIdFinderObserver
{
private $userID;
public function __construct(){
$this->userID = auth()->id();
}
public function saving($model)
{
$model->created_by = $this->userID;
}
public function updating($model){
$model->updated_by = $this->userID;
}
public function creating($model)
{
$model->created_by = $this->userID;
}
public function deleting($model)
{
$model->deleted_by = $this->userID;
}
}

Completion system with Laravel + VueJS

I've been tring for hours to define my relations for a completion system but I failed.
I have a table Users and a table Episodes, and I would like to get in my views if the User has completed an episode.
I created a "completions" table with user_id and episode_id and a boolean field called "completed"
Is it a manytomany relation ? I'd like to have something like $episode->completed which gave me True if the logged in user finished the course, but I can't find my way... I just wanna know how to define my relations, not a whole work done.
Thank you very much !!!!
I believe you can tell Laravel what table to use and also query the pivot column.
//user model
public function episodes(){
return $this->belongsToMany( 'App\Episode', 'completions', 'user_id', 'episode_id' );
}
public function completedEpisodes(){
return $this->belongsToMany( 'App\Episode', 'completions', 'user_id', 'episode_id' )
->wherePivot('completed','=', true)->get();
}
//episode model
public function users(){
return $this->belongsToMany( 'App\User', 'completions', 'episode_id', 'user_id' );
}
The alternative would be to create your pivot as episode_user and laravel will auto detect it as the pivot, add a completed boolean to that table and it would function with just:
//user model
public function episodes(){
return $this->belongsToMany('App\Episode');
}
public function completedEpisodes(){
return $this->belongsToMany('App\Episode')
->wherePivot('completed','=', true)->get();
}
//episode model
public function users(){
return $this->belongsToMany('App\User');
}
Query if episode is complete:
//maybe, haven't tried this
//user
public function hasCompletedEpisode($id){
return $this->belongsToMany('App\Episode')->wherePivot('episode_id','=', $id)
->wherePivot('completed','=', true)->get();
}
//episode
public function hasCompletedEpisode($id){
$user_id = Auth::id();
return $this->belongsToMany('App\User')->wherePivot('user_id','=', $user_id)
->wherePivot('completed', true)->get();
}
If I was you, I would use a custom intermediate table. You can implement this as follows:
Migrations
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('episodes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
Schema::create('watches', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('epsiode_id');
$table->boolean('completed');
$table->timestamps();
});
Models
class User extends Model
{
protected $guarded = [];
public function watchedEpisodes()
{
return $this->hasMany(Episode::class)->using(Watch::class);
}
public function watches()
{
return $this->hasMany(Watch::class);
}
}
class Episode extends Model
{
protected $guarded = [];
public function users()
{
return $this->hasMany(User::class)->using(Watch::class);
}
}
class Watch extends \Illuminate\Database\Eloquent\Relations\Pivot
{
protected $table = 'watches';
protected $guarded = [];
public static function create(User $user, Episode $episode, bool $completed = false)
{
$watch = new self();
$watch->user_id = $user->id;
$watch->epsiode_id = $episode->id;
$watch->completed = $completed;
$watch->save();
return $watch;
}
public function user()
{
return $this->hasOne(User::class);
}
public function episode()
{
return $this->hasOne(User::class);
}
}
Example Use
$user = User::create(['name' => 'Big Watcher']);
$episode1 = Episode::create(['name' => 'Episode 1']);
$episode2 = Episode::create(['name' => 'Episode 2']);
$episode3 = Episode::create(['name' => 'Episode 3']);
$episode4 = Episode::create(['name' => 'Episode 4']);
Watch::create($user, $episode1);
Watch::create($user, $episode2);
Watch::create($user, $episode3);
return $user->watchedEpisodes;

My hasMany in laravel response null, my model its correct

I have problem my has many relation response null.
this is my model
class Diskusi extends Model
{
protected $table = 'tbl_diskusi';
protected $hidden = [
'topic'
];
public function user(){
return $this->belongsTo(User::class,'id_user');
}
public function category(){
return $this->belongsTo(Category::class);
}
public function pets_category(){
return $this->belongsTo(PetsCategory::class);
}
}
this is my another model
class PetsCategory extends Model
{
//
protected $table = 'tbl_pets_category';
public function diskusi(){
return $this->hasMany(Diskusi::class,'id_pets_category');
}
}
and another
class Category extends Model
{
//
protected $table = 'tbl_category';
public function diskusi(){
return $this->hasMany(Diskusi::class,'id_category');
}
}
and this is my migration for Diskusi
class CreateTblDiskusi extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('tbl_diskusi', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->string('content');
$table->string('topic');
$table->unsignedBigInteger('id_user');
$table->unsignedBigInteger('id_category');
$table->unsignedBigInteger('id_pets_category');
$table->timestamps();
$table->foreign('id_user')->references('id')
->on('users')->onDelete('cascade');
$table->foreign('id_category')->references('id')
->on('tbl_category')->onDelete('cascade');
$table->foreign('id_pets_category')->references('id')
->on('tbl_pets_category')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('tbl_diskusi');
}
}
the condition is
i want my Diskusi have one category, and one pets_category
but when i create Diskusi like this
public function create(Request $request)
{
$diskusi = new Diskusi;
$diskusi->title = $request->title;
$diskusi->content = $request->content;
$diskusi->topic = $request->topic;
$diskusi->id_user = Auth::user()->id;
$diskusi->id_category = $request->id_category;
$diskusi->id_pets_category = $request->id_pets_category;
if ($request->photo != ''){
foreach ($request->photo as $itemPhoto) {
# code...
$photo = new Photo;
$rand = $this->generateRandomString() . 'jpg';
//taroh foto di server
// file_put_contents('storage/photo/diskusi/' . $rand , base64_decode($request->photo));
$photo->path_photo = $rand;
$photo->save();
}
}
$diskusi->save();
$diskusi->user;
$diskusi->category;
$diskusi->pets_category;
return response()->json([
'success' => true,
'message' => 'posted',
'post' => $diskusi
]);
}
the response like this
please help me, i tried with many tutorial relational laravel but it's not working for me. i dont know where my false, please tell me my false.
*note: sorry for bad english
You've to define your foreign key in relationship.
public function category(){
return $this->belongsTo(Category::class,'id_category','id');
}
public function pets_category(){
return $this->belongsTo(PetsCategory::class,'id_pets_category','id');
}
If you don't pass the foreign key then by default it judges 'category_id' or 'pets_category_id' but you've given id_category and id_pets_category

Laravel many-to-many relation with custom table names and IDs

Hello so I have many to many relation between Question [table name: tblquestion, id: que_id] and Agecategory [table name: tblagecategory, id: aca_id]. They have shared table named QuestionAgecategory [table name: tblquestionagecategory, id: qac_id].
I want to note that all the IDS and table names are custom named and not according to typical Laravel syntax.
And I am trying to relate them in Laravel. So far it returns null when I try to look $question->agecategories;
$question->agecategories;
=> null
But it has records in it and returns this after $question = App\Question::find(1);
$question = App\Question::find(1);
=> App\Question {#2901
que_id: 1,
que_name: "hello",
Question model
class Question extends Model
{
protected $table = 'tblquestion';
protected $primaryKey = 'que_id';
protected $keyType = 'integer';
public $incrementing = true;
public $timestamps = false;
public function agecategories()
{
return $this->belongsToMany('App\Agecategory');
}
}
Agecategory model
class Agecategory extends Model
{
protected $table = 'tblagecategory';
protected $primaryKey = 'aca_id';
protected $keyType = 'integer';
public $incrementing = true;
public function questions()
{
return $this->belongsToMany('App\Question');
}
}
QuestionAgecategory model
class QuestionAgecategory extends Model
{
protected $table = 'tblquestionagecategory';
protected $primaryKey = 'qac_id';
protected $keyType = 'integer';
public $incrementing = true;
}
Migrations
Schema::create('tblquestion', function (Blueprint $table) {
$table->increments('que_id');
$table->string('que_name', 128);
});
Schema::create('tblagecategory', function (Blueprint $table) {
$table->increments('aca_id');
$table->timestamps();
});
Schema::create('tblquestionagecategory', function (Blueprint $table) {
$table->increments('qac_id');
$table->integer('qac_que_id')->unsigned();
$table->integer('qac_aca_id')->unsigned();
$table->foreign('qac_que_id')->references('que_id')->on('tblquestion');
$table->foreign('qac_aca_id')->references('aca_id')->on('tblagecategory');
});
You are using custom columns and custom database naming.
Your Belongs to many is expecting a pivot table tblquestion_tblagecategory which does not exist. As the previos answer stated, you should change your belongsToMany to search for the custom tables and columns.
https://laravel.com/docs/5.6/eloquent-relationships#many-to-many
Change to this in your question Model
public function agecategories()
{
return $this->belongsToMany('App\Agecategory', 'tblquestionagecategory', 'qac_que_id', 'qac_aca_id');
}
And also, in your other Agecategory Model
public function questions()
{
return $this->belongsToMany('App\Question', 'tblquestionagecategory', 'qac_aca_id', 'qac_que_id');
}
add below relationship function in Question model
public function agecategories()
{
return $this->belongsToMany('App\Agecategory', 'tblquestionagecategory', 'qac_que_id', 'qac_aca_id');
}
I encountered the same problem but I had to declare only the foreign keys without a prefix like this:
public function agecategories()
{
return $this->belongsToMany('App\Agecategory', 'tblquestionagecategory', 'que_id', 'aca_id');
}

How to make user, and roles relationship in Laravel 5

I have two tables :
User ->
id :
name :
role_id : ->references('id')->on('roles');
Roles ->
id :
role_name :
access :
I am trying to access roles details from user.
My User model has:
public function role()
{
return $this->belongsTo('App\Role');
}
My Role model has:
public function user()
{
return $this->hasMany('App\User');
}
When I try to do following :
$user = User::find(1);
$details = [
'name' => $user->first_name,
'role' => $user->role->role_name
];
I get error :
Trying to get property of non-object
My roles table contains access columns containing array of permissions to different routes. So my user will have only one role. While a role can have multiple users.
How to do that?
In my recent project, I handled these requirement in that way..
First of All Database Table Structure/Migration
User Table
class CreateUserTable extends Migration {
public function up() {
Schema::create('user', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->boolean('status')->default(0);
$table->boolean('is_admin')->default(0);
$table->boolean('notify')->default(0);
$table->rememberToken();
$table->timestamps();
});
}
public function down() {
Schema::drop('user');
}
}
Role Table
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRoleTable extends Migration {
public function up()
{
Schema::create('role', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('display_name')->nullable();
$table->string('description')->nullable();
$table->boolean('status')->default(0);
$table->timestamps();
});
}
public function down()
{
Schema::drop('role');
}
}
Role And User Relation Table
class CreateRoleUserTable extends Migration {
public function up() {
// Create table for associating roles to users (Many-to-Many)
Schema::create('role_user', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('user_id')->references('id')->on('user')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('role')
->onUpdate('cascade')->onDelete('cascade');
$table->primary(['user_id', 'role_id']);
});
}
public function down() {
Schema::drop('role_user');
}
}
After these table you have to handle permission by assigning to specific Role.
Permission
class Permission extends Migration {
public function up() {
Schema::create('permission', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('pattern');
$table->string('target');
$table->string('module');
$table->string('display_name')->nullable();
$table->boolean('status')->default(0);
$table->timestamps();
});
}
public function down() {
Schema::drop('permission');
}
}
Permission and Role Table Relation
class PermissionRole extends Migration {
public function up() {
// Create table for associating roles to permission (Many-to-Many)
Schema::create('permission_role', function (Blueprint $table) {
$table->integer('permission_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('permission_id')->references('id')->on('permission')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('role')
->onUpdate('cascade')->onDelete('cascade');
$table->primary(['permission_id', 'role_id']);
});
}
public function down() {
Schema::drop('permission_role');
}
}
And Finally our model would look alike:
User Model
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
use Authenticatable, CanResetPassword;
protected $table = 'user';
protected $fillable = ['name', 'email', 'password', 'is_admin'];
protected $hidden = ['password', 'remember_token'];
public function scopeActive($query) {
return $query->whereStatus('1');
}
public function scopeAdmin($query) {
return $query->whereIsAdmin('1');
}
public function scopeNotify($query) {
return $query->whereNotify('1');
}
public function roles() {
return $this->belongsToMany('App\Role', 'role_user', 'user_id', 'role_id');
}
public function attachRole($role) {
if (is_object($role)) {
$role = $role->getKey();
}
if (is_array($role)) {
$role = $role['id'];
}
$this->roles()->attach($role);
}
public function detachRole($role) {
if (is_object($role)) {
$role = $role->getKey();
}
if (is_array($role)) {
$role = $role['id'];
}
$this->roles()->detach($role);
}
public function attachRoles($roles) {
foreach ($roles as $role) {
$this->attachRole($role);
}
}
public function detachRoles($roles) {
foreach ($roles as $role) {
$this->detachRole($role);
}
}
public function isSuperUser() {
return (bool)$this->is_admin;
}
public function hasAccess($permissions, $all = true) {
if ($this->isSuperUser()) {
return true;
}
return $this->hasPermission($permissions, $all);
}
public function hasPermission($permissions) {
$mergedPermissions = $this->getMergedPermissions();
//dd($mergedPermissions);
if (!is_array($permissions)) {
$permissions = (array)$permissions;
}
foreach ($permissions as $permission) {
$matched = false;
// We will set a flag now for whether this permission was
// matched at all.
$founded_perms = find_in($mergedPermissions, "name", $permission);
if (!empty($founded_perms)) {
$matched = true;
}
}
if ($matched === false) {
return false;
}
return true;
}
public function getMergedPermissions() {
$permissions = array();
foreach ($this->getRoles() as $group) {
$permissions = array_merge($permissions, $group->permissions()->get()->toArray());
}
return $permissions;
}
public function getRoles() {
$roles = [];
if ($this->roles()) {
$roles = $this->roles()->get();
}
return $roles;
}
}
Role Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Role extends Model {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'role';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'display_name', 'description'];
public function scopeActive($query) {
return $query->whereStatus('1');
}
/**
* Many-to-Many relations with User.
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users() {
return $this->belongsToMany('App\User');
}
public function permissions() {
return $this->belongsToMany("App\Permission");
}
}
Permission Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model {
protected $table = 'permission';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name', 'pattern', 'target', 'module', 'display_name', 'status'];
public static function displayable() {
$prepared_array = [];
$temp = self::orderBy('module')->get()->toArray();
foreach ($temp as $sin) {
$prepared_array[$sin['module']][] = $sin;
}
return $prepared_array;
}
public function scopeActive($query) {
return $query->whereStatus('1');
}
public function roles() {
return $this->belongsToMany("App\Role");
}
}
Well, thats the basic structure helped to implement basic ACL and Auth with laravel 5.
Let me know if you have any further related question. Or If you need complete implementation I'll provide it to you.
For a one-to-many relationship you don't need a pivot table, so you can delete the user_roles table. Then add a role_id column to your users table, that will reference the id column in for your roles table. Next define the relations as follows for each of your models:
// User.php
public function role()
{
return $this->belongsTo('App\Role');
}
and
// Role.php
public function users()
{
return $this->hasMany('App\User');
}
Now you can access your role via the relation like this:
$user->role->name;
I got the problem, i was having a role column in user table, so when i was doing
$user->role->role_name
it was fetching role column instead of relationship.
i noticed you are not using the laravel default table naming conventions,
you are using user_roles whereass laravel naming conventions state you should use:
role_user (alphabetical and singular)
you could override the belongsToMany by stating your custom table name ofcource.
public function users() {
return $this->belongsToMany('App\User', 'user_roles');
}
on the second node there are also some good libraries to handle these kind of things, take a look at : https://github.com/romanbican/roles

Resources