Completion system with Laravel + VueJS - laravel

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;

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;
}
}

How can i store more than one product_ticket?

Im trying to store more than one product with my controller. In my function store first i generate a ticket and then i generate a product_ticket with the ticket_id recently generated and the product_id from the selected product from the form. But how can i do to store more than one if i select more than one product in the form.
This are my relationships:
Product.php:
class Product extends Model
{
public function tickets()
{
return $this->belongsToMany(Ticket::class);
}
public function productXticket()
{
return $this->hasMany(ProductXTicket::class);
}
}
Ticket.php
class Ticket extends Model
{
public function productXticket()
{
return $this->hasMany(ProductXTicket::class);
}
public function products()
{
return $this->belongsToMany(Product::class);
}
}
ProductXTicket:
class ProductXTicket extends Model
{
protected $table = 'product_ticket';
public function ticket_id(){
return $this->belongsTo(Ticket::class);
}
public function product_id(){
return $this->belongsTo(Product::class);
}
}
product_ticket migration:
Schema::create('product_ticket', function (Blueprint $table) {
$table->id();
$table->foreignId('product_id')->constrained();
$table->foreignId('ticket_id')->constrained();
$table->string('serial_number');
$table->integer('quantity');
$table->timestamps();
});
}
TicketController:
public function store(Request $request){
/*dd($request->all());*/
$ticket = new Ticket();
/*$ticket->cuenta_id = $request->cuenta_id;*/
$ticket->contact_id = $request->contact_id;
$ticket->statusTicket_id = $request->statusTicket_id;
$ticket->typeTicket_id = $request->typeTicket_id;
$ticket->idOwner = Auth::user()->id;
$ticket->save();
$productXticket = new ProductXTicket();
$productXticket->ticket_id = $ticket->id;
$productXticket->serial_number = $request->serial_number;
$productXticket->quantity = $request->quantity;
$ticket->productXticket()->save($productXticket);
Session::flash('success');
return redirect()->route('tickets.view');
}
So here im storing one ticket and one product_ticket. I want form each ticket to store the same amount of product_ticket as the amount products selected
Instead of:
$ticket->productXticket()->save($productXticket);
Use:
$ticket->productXticket()->saveMany([$productXticket,...]);

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

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']);

I want to return a user with a list of all the people they have referred by there username

I am developing a referral system in my software. I have gotten the referral right but I want to list all users the auth users have referred.
Note: I am writing an API endpoint so I cant use a relationship to display their name.
Here is my user model
public function referrals()
{
return $this->hasMany(Referral::class, 'user_id', 'id');
}
public function referrer()
{
return $this->hasOne(Referral::class, 'referred_by', 'id');
}
Note: referred_by is the person that has referred someone and user_id is the person referred
Here is my referral model
protected $fillable = ['user_id', 'referred_by', 'status'];
public function user()
{
return $this->belongsTo(User::class);
}
Here is my referrals migration
Schema::create('referrals', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned()->references('id')->on('users');
$table->integer('referred_by')->unsigned()->references('id')->on('users');
$table->string('status')->nullable();
$table->timestamps();
});
User Model
// Referrals given by the user.
public function referralsGiven()
{
return $this->hasMany(App\Referral::class, 'referred_by', 'id');
}
Referral Model
//Person who got the referral
public function user()
{
return $this->belongsTo(App\User::class, 'user_id', 'id');
}
public function referredBy()
{
return $this->belongsTo(App\User::class, 'referred_by', 'id');
}
pluck collection method https://laravel.com/docs/7.x/collections#method-pluck
Controller
$user = User::with('referralsGiven.user')->find(Auth::user()->id);
$users_reffered_by_Auth_user = $user->referralsGiven->pluck('user');
OR
$referrals = Referral::with('user')->where('reffered_by', Auth::user()->id)->get();
$users_reffered_by_Auth_user = $referrals->pluck('user');

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