Laravel Many-to-Many Pivot Table - laravel

I have a fairly simple question about the use of Pivot tables in laravel. Firstly ill give some information about my situation, I have two tables name "Vehicles", and "Events". Now I would like to create a table that will be used to hold vehicles that have registered for an event. Now the relationship that between these two tables would be that "Many Vehicles can register for Many Events" and vice versa. would a Pivot table be the best way to accomplish this, and if so could more singular values be in the same table?

You can associate an event with multiple vehicles and a vehicle to multiple events by doing something like this with your models (not tested):
Vehicle.php
<?php
namespace App;
use App\Event;
use Illuminate\Database\Eloquent\Model;
class Vehicle extends Model
{
...
/**
* Get the events that this vehicle belongs to.
*
* #return \App\Event
*/
public function events()
{
return $this->belongsToMany(Event::class, 'vehicle_event');
}
}
Event.php
<?php
namespace App;
use App\Vehicle;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
...
/**
* Get the vehicles that this event has.
*
* #return \App\Vehicle
*/
public function events()
{
return $this->hasMany(Vehicle::class, 'vehicle_event');
}
}
You'll also need a migration file for the pivot table:
...
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('vehicle_event', function(Blueprint $table)
{
$table->integer('vehicle_id')->unsigned()->index();
$table->foreign('vehicle_id')->references('id')->on('vehicles');
$table->integer('event_id')->unsigned()->index();
$table->foreign('event_id')->references('id')->on('events');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('vehicle_event');
}
...
Then you can to use attach() and detach() to associate vehicles with events or vice versa.

Related

Laravel model - CRUD only with records where one column = certain value?

Suppose i have a laravel model that works with a certain (MySQL) database table.
Inside of this table there is a column named 'administration'. (example: could be 1, 2 or 3)
At the moment in my controller im using that modal with eloquent and inside of my eloquent statement i ask only to work with records (crud style) that have administration 2 for instance.
I think it should be possible to add 'where administration = x' to my model instead of my controller so that if i use the model in my controller i would just be dealing with records that have that administration set.
Is this possible? I have tried googling it but could not find an answer yet.
Laravel uses global scopes for this.
You would create a scope for the administration:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
class AdministrationScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('administration', '=', 2);
}
}
And then you add it as a global scope to the model
<?php
namespace App\Models;
use App\Scopes\AdministrationScope;
use Illuminate\Database\Eloquent\Model;
class YourModel extends Model
{
/**
* The "booted" method of the model.
*
* #return void
*/
protected static function booted()
{
static::addGlobalScope(new AdministrationScope);
}
}

How to do hasMany and belongsToMany at same model?

I have 2 models, Employee & FieldReport. I need to create relations based on the following conditions:
Field report is owned by an employee whose character is absolute
(owner's data must be displayed and cannot be edited), where the
report field also has a tag to mark who the employees are in that
report field.
An employee, himself, has many field reports.
For now, I've made a relationship, something like this:
Employee has many Field Reports.
Employee belongs to many Field Reports.
Field Report belongs to Employee.
Field Report belongs to many Employees.
Then I have a problem where PHP doesn't allow the same method name (in the Employee model).
Example:
Has many has the method name fieldReports ()
Belongs to many also have the method name fieldReports ()
Whereas if I define the function name custom, I cannot get the value to fill the first pivot column and generate an error like the following:
SQLSTATE [23000]: Integrity constraint violation: 19 NOT NULL
constraint failed: field_report_participant.field_report_id (SQL:
insert into "field_report_participant" ("id", "participant_id") values
​​(1, 2))
Is there any solution? This is how my scripts looks like:
Employee.php
/**
* Each employee has many fieldReports.
*
* #return \Illuminate\Database\Eloquent\Relationship\HasMany
*/
public function fieldReports()
{
return $this->hasMany(FieldReport::class);
}
/**
* Each employee belongs to many fieldReports.
*
* #return \Illuminate\Database\Eloquent\Relationship\BelongsToMany
*/
public function fieldReports()
{
return $this->belongsToMany(FieldReport::class);
}
FieldReportController.php
/**
* Store a newly created resource in storage.
*
* #param \App\Http\Requests\RequestFieldReport $request
* #return \Illuminate\Http\Response
*/
public function store(RequestFieldReport $request)
{
$fieldReport = $this->data($request, $this->storeImages($request));
$fieldReport->participants()->sync(
$request->participants
);
return response()->json([
'created' => true,
'data' => $fieldReport,
], 201);
}
FieldReport.php
/**
* Each field report belongs to a company.
*
* #return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function company()
{
return $this->belongsTo(Company::class);
}
/**
* Each field report belongs to a employee.
*
* #return \Illuminate\Database\Eloquent\Relationship\BelongsTo
*/
public function employee()
{
return $this->belongsTo(Employee::class);
}
/**
* Each field report belongs to many participants.
*
* #return \Illuminate\Database\Eloquent\Relationship\BelongsToMany
*/
public function participants()
{
return $this->belongsToMany(Employee::class, 'field_report_participant', 'participant_id', 'id');
}
create_field_reports_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFieldReportsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('field_reports', function (Blueprint $table) {
$table->id();
$table->bigInteger('company_id');
$table->bigInteger('employee_id');
$table->string('title', 100);
$table->text('chronology');
$table->json('images')->nullable();
$table->timestamp('closed_at')->nullable();
$table->string('closed_by', 100)->nullable();
$table->timestamp('opened_at')->nullable();
$table->string('opened_by', 100)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('field_reports');
}
}
field_report_participant_table.php
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFieldReportParticipantTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('field_report_participant', function (Blueprint $table) {
$table->id();
$table->bigInteger('field_report_id');
$table->bigInteger('participant_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('field_report_participant');
}
}
After an hour pulling off my hair, trying to do a backflip and asked on each different forums, finally I had the answer. Unfortunately, he has no account on this forum and can't give the answer for this question.
The problem is I put a wrong key on the participants method which causing the field_report_id placed in a wrong place, in this case; id. Which is solved by doing this:
/**
* Each field report belongs to many participants.
*
* #return \Illuminate\Database\Eloquent\Relationship\BelongsToMany
*/
public function participants()
{
return $this->belongsToMany(Employee::class, 'field_report_participant', 'field_report_id', 'participant_id');
}
And then, on the Employee class, I could create exactly different method and link it with the pivot table. Like this:
/**
* Each employee belongs to many assignedFieldReports.
*
* #return \Illuminate\Database\Eloquent\Relationship\BelongsToMany
*/
public function assignedFieldReports()
{
return $this->belongsToMany(FieldReport::class, 'field_report_participant', 'participant_id', 'field_report_id');
}
Hopefully, it can help someone facing this exact same issue on the future.

only approved column returned back on any relationship

i have table products.
i need make something in model only return product where approved is equal to 1
this my schema
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->text('description');
$table->unsignedInteger('quantity');
$table->unsignedInteger('subcategory_id')
->references('id')->on('subcategories')->onDelete('cascade');
$table->decimal('price');
$table->decimal('discount_price');
$table->decimal('super_discount')->nullable();
$table->string('cover');
$table->unsignedInteger('brand_id')
->references('id')->on('brands')->onDelete('cascade');
$table->unsignedInteger('category_id')
->references('id')->on('categories');
$table->string('color');
$table->string('size_id')->references('id')->on('sizes')->nullable();
$table->decimal('rate');
$table->enum('made_in',['turkey','china','egypt']);
$table->string('serial');
$table->boolean('approved')->default(0);
$table->timestamps();
$table->unique(['name','size_id','color']);
});
i hope this is valid.
You can make use of Global Scopes
Global scopes allow you to add constraints to all queries for a given
model. Laravel's own soft deleting functionality utilizes global
scopes to only pull "non-deleted" models from the database. Writing
your own global scopes can provide a convenient, easy way to make sure
every query for a given model receives certain constraints.
Writing Global Scopes Writing a global scope is simple. Define a class
that implements the Illuminate\Database\Eloquent\Scope interface. This
interface requires you to implement one method: apply. The apply
method may add where constraints to the query as needed:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class ApprovedScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
return $builder->where('approved', 1);
}
}
There is not a predefined folder for scopes in a default Laravel
application, so feel free to make your own Scopes folder within your
Laravel application's app directory.
Applying Global Scopes To assign a global scope to a model, you should
override a given model's boot method and use the addGlobalScope
method:
<?php
namespace App;
use App\Scopes\ApprovedScope;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::addGlobalScope(new ApprovedScope);
}
}
After adding the scope, a query to Product::all() will produce the
following SQL:
select * from `products` where `approved` = 1
Docs

Eloquent how to do something when delete or update operate on a special model

Most of my db table contain create_user_id and update_user_id
How can l update this two field automatic when l use save(), update(), insert(), createOrUpdate() and etc method.
For example, l execute this script:
$model = Model::find(1);
$model->model_f = 'update';
$model->save();
then this record's model_f updated, and update_user_id updated, too.
l know eloquent can manage update_time automatic and l have use it already. But l want to do something else when update or insert or delete
PS: l have a constant named USERID to remember current user's id
You could make use of Observers.
You can hook to the following events on your Model:
retrieved
creating
created
updating
updated
saving
saved
deleting
deleted
restoring
restored
Let me give you an example where we are trying to hook into the events emitted by the App/User model. You can change this to match your particular Model later on.
To create an observer, run the following command:
php artisan make:observer UserObserver --model=User
Then you can hook to specific events in your observer.
<?php
namespace App\Observers;
use App\User;
class UserObserver
{
/**
* Handle the User "saved" event.
*
* #param \App\User $user
* #return void
*/
public function saved(User $user)
{
//
}
/**
* Handle the User "created" event.
*
* #param \App\User $user
* #return void
*/
public function created(User $user)
{
//
}
/**
* Handle the User "updated" event.
*
* #param \App\User $user
* #return void
*/
public function updated(User $user)
{
//
}
}
Since, in your particular case, you want to hook into these 3 events, you can define the events above and perform additional operations to your model when those events are called.
Don't forget to register this observer in your AppServiceProvider.
<?php
namespace App\Providers;
use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
User::observe(UserObserver::class);
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
//
}
}
There is pretty simple way to automatically update the create_user_id and update_user_id
Step1:
Open you app folder and create the new file named as UserStampsTrait.php
Step:2
and paste the following code
<?php
namespace App;
use Illuminate\Support\Facades\Auth;
trait UserStampsTrait
{
public static function boot()
{
parent::boot();
// first we tell the model what to do on a creating event
static::creating(function($modelName='')
{
$createdByColumnName = 'create_user_id ';
$modelName->$createdByColumnName = Auth::id();
});
// // then we tell the model what to do on an updating event
static::updating(function($modelName='')
{
$updatedByColumnName = 'update_user_id';
$modelName->$updatedByColumnName = Auth::id();
});
}
}
Thats it
Step:3
Open you model which needs to updated the corresponding models automatically
for Example it may be Post
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use App\UserStampsTrait;
class Post extends Model
{
use UserStampsTrait;
}
Thats it

How to save One to Many Relationship to database

Below is my LevelOneModel. I can't seem to figure out what I have not included. Please I need assistance.
What I want to achieve is to have all the users id in the levelone table
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class LevelOneModel extends Model
{
public function users(){
return $this->hasMany('App\User');
}
}
Below is my User model
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'first_name',
'last_name',
'email',
'phone',
'bank_name',
'acct_name',
'acct_number',
'profile_pix',
'sme',
'other_sme',
'password',
];
public function levelone()
{
return $this->belongsTo('App\LevelOneModel');
}
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
And below is my level one migration file
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateLevelOneTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('level_one', function (Blueprint $table) {
$table->increments('id');
$table->integer('users_id')->unsigned();
$table->integer('upline_id')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('level_one');
}
}
Thanks
I notice some things in your code....
Looking at your classes, I understand the relationship is like this
a user belongs to one LevelOne only.
a LevelOne can have multiple users
If that is correct, the relationship is incorrectly build in the migration. Because you are adding a user_id to the level_one table.
It should be the other way around: the user tabel must contain a level_one_id.
And you should add it in the User migration, something like:
$table->int('level_one_id');
$table->foreign('level_one_id')->references('id')->on('level_one');
Now you have (in the database) a connection between User and LevelOne.
Now, if you query a user in your code, you should be able to get the LevelOne stuff as well. Make sure to really read the official Laravel documentation on relationships! It will really help you with examples.

Resources