I have two table:
1. Rooms
2. Facilities
The Facilities rooms contains the id and a varchar column.
The Room table contains a columns (facilities_id) with, obviously, the id from the facilities table. In that column I have a multiple value, separated by a comma (1,3,4).
What is the best way to make a relation between them? Like "belongsTo" relations but with multi ids.
Like Alexander M. said, would be better if you change your structure. e. g.:
Schema::create('facilities', function (Blueprint $table) {
$table->increments('id');
$table->string('column')->unique();
$table->timestamps();
});
Schema::create('facility_room', function (Blueprint $table) {
$table->integer('facility_id')->unsigned();
$table->integer('room_id')->unsigned();
$table->foreign('facility_id')->references('id')->on('facilities')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('room_id')->references('id')->on('rooms')
->onUpdate('cascade')->onDelete('cascade');
});
Schema::create('rooms', function (Blueprint $table) {
$table->increments('id');
$table->string('column')->unique();
$table->timestamps();
});
In your Facility Model:
public function rooms()
{
return $this->belongsToMany(Room::class);
}
In your Room Model:
public function facilities()
{
return $this->belongsToMany(Facility::class);
}
In our application:
$room = Room::find($id);
$facilities = $room->facilities();
As #jedrzej.kurylo said, you need a many to many relation. String ids as a comma-separated list is wrong, it violates the First normal form and is extremely inconvenient to use.
So you should rethink your model structure.
Related
So I am having troubles on how to implement multiple authors in one paper and how to separate authors to be used for citations of a paper.
currently I have my input like this
<div class="group">
<input class="inputchecker2 inputInfo" id="inputID" type="text" name="Authors" required>
<span class="highlight"></span>
<span class="bar"></span>
<label class="infoLabel">Author(s)</label>
</div>
where name="Authors" is stored like this in the controller
$paper=new Papers();
$paper->Authors=$request->Authors;
The problem arises once there are multiple authors in one paper and I don't know how to implement that and make it work I tried making another table for it but I got stuck in thinking of the Logic
my migration files is as follows:
PAPERS TABLE
public function up()
{
Schema::create('papers', function (Blueprint $table) {
$table->id('PaperID');
$table->string('PaperTitle');
$table->string('PaperType');
$table->string('Authors');
$table->string('College')->nullable();
$table->string('file');
$table->date('DatePublished')->nullable();
$table->unsignedBigInteger('UploaderUserID');
$table->foreign('UploaderUserID')->references('UserID')->on('users');
$table->timestamps();
});
}
AUTHORS TABLE
public function up()
{
Schema::create('paper_authors', function (Blueprint $table) {
$table->id('PaperAuthorID');
$table->unsignedBigInteger('paper_ID');
$table->foreign('paper_ID')->references('PaperID')->on('papers');
$table->string('AuthorName');
$table->unsignedBigInteger('user_ID');
$table->foreign('user_ID')->references('UserID')->on('users');
$table->timestamps();
});
}
Are there ways in simplifying this to make it easier for me to understand?
Your approach is kind of wrong from the start,
A paper can belong to multiple authors
An author can have multiple papers.
In your paper model, you should have this
public function authors(){
return $this->belongsTo(Author::class);
}
In your author model, you should have this
public function papers(){
return $this->belongsTo(Paper::class);
}
Your Paper migration should look like this
public function up()
{
Schema::create('author_papers', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('author_id');
$table->foreign('user_id')->references('user_id')->on('users');
$table->string('title');
$table->string('type');
$table->string('college')->nullable();
$table->string('file');
$table->date('date_published')->nullable();
$table->timestamps();
});
}
Please note that I have changed some of the table columns to the Laravel convention (lowercase, snake_case instead of camelCase), the same will be done will the authors' table. I changed PaperIdD to id, I changed the table name to author_papers too. I made a lot of changes, check them and do what works for you. The important thing is to add author_id to the table
public function up()
{
Schema::create('authors', function (Blueprint $table) {
$table->id('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_ID')->references('UserID')->on('users');
$table->string('name');
$table->timestamps();
});
}
You don't need to add the paper id here, as one author can have many papers.
The last thing, a plus actually, when creating a new paper, you will need to send a list of all the authors to the HTML blade. So, the part the user will enter the author name will now be Select and not input again.
Best of success
So from my previous post, I was advised to start using Eloquent models, which I did.
My end goal, is to print out specific gifts, that belongs to that specific box.
Migrations:
gift_items:
public function up()
{
Schema::create('gift_items', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->float('unit_price');
$table->integer('units_owned');
});
}
gift_campaigns:
public function up()
{
Schema::create('gift_campaigns', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('user_foreignK')->constrained('users');
$table->integer('gift_item_count')->nullable();
$table->string('status');
$table->date('dispatch_date');
$table->date('delivery_date');
});
}
Pivot table:
public function up()
{
Schema::create('campaigns_gifts', function (Blueprint $table) {
$table->foreignId('gift_id')->constrained('gift_items');
$table->foreignId('campaign_id')->constrained('gift_campaigns');
});
}
Controller:
function box($id){
$data = Campaign::with('gifts')->where('id', $id)->get();
return view('DBqueries.boxView', ['data'=>$data]);
}
Error that I receive using this way:
Seems like the updated version is trying to call the gift_campaigns table id, instead of the pivots table campaign_id.
Once again, I need that Request $id would match the pivots table campaign_id, and print out all of the gifts that this specific id holds
First of all as I sense the campaigns_gifts is a pivot table for campaigns and gifts having a Many-to-Many relation. You are doing it completely against the conventions of Laravel.
You generally do not use a Model for pivot table.
You generally do not fetch data from the pivot table directly. Instead use the relation on one of the related Models.
Note: Laravel does allow a Model for a Pivot, and you can query the pivot table directly, just check the documentation.
The correct way:
Pivot
Make a pivot table (that you already have) with column gift_id and campaign_id. i.e., the convention for naming keys as [table_name_singular]_[primary_key_on_table]
Model
One each model, define relationship for the other data as:
Gift.php Model:
public function campaign() {
return $this->belongsToMany(Campaign::class, 'campaign_gift');
}
Campaign.php Model:
public function gifts() {
return $this->belongsToMany(Gift::class,'campaign_gift');
}
since gift have a hasMany relation, the gifts table must contain a foreign key to campaigns table named campaign_id (same as the one on pivot).
Controller
Now in your controller:
function box($id){
$data = Campaign::where('id',$id)->with('gifts')->get();
return view('DBqueries.boxView', ['data'=>$data]);
}
You don't need to tell Laravel which columns, tables etc are you referring to, as long as you follow the conventions, Laravel will magically do things that otherwise would have been much more painful.
I would like to add a custom prefix to UUIDs within Laravel to help keep better track of Database entries. Currently, when called, the uuid(); function will produce a table entry like this:
6ab4a8c-9597-lle7-a63c-0242c100426l
But I would like to be able to a a prefix infront of every uuid entry within that table. For instance, Users within the Users table would have a uuid prefixed with UUID of:
UUID-6ab4a8c-9597-lle7-a63c-0242c100426l
and Posts would be saved in the Posts table with a PUID prefix:
PUID-6ab4a8c-9597-lle7-a63c-0242c100426l
to signify ('Post' Unique Identifier).
The default migration for the Users table is as follows:
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
To use UUIDs, the following would be used:
Schema::create('users', function (Blueprint $table) {
$table->uuid('uuid')->primary();
});
I'm not sure where the models defining UUID(s) are stored, and I'm not sure I'd want to modify the entire model.
Ideally, the a uuid would be defined using the table name, then the prefix as such:
$table->uuid('puid', 'PUID')->primary();
Does anyone know how this could be implemented?
Thanks in advance.
You can use an accessor and a mutator to achieve what you want in your frontend, but the database will contain an UUID formatted value, because it's an UUID column.
In your Users model:
public function getUuidAttribute($value)
{
return "UUID-".$value;
}
public function setUuidAttribute($value)
{
$this->attributes['uuid'] = str_replace("UUID-", "", $value);
}
and in your Posts Model:
public function getPuidAttribute($value)
{
return "PUID-".$value;
}
public function setPuidAttribute($value)
{
$this->attributes['puid'] = str_replace("PUID-", "", $value);
}
you will see UUID-6ab4a8c-9597-lle7-a63c-0242c100426l when you dump $user->uuid and same will happen with $post->puid with a prefix of PUID-.
Otherwise, you should generate your UUID's yourself, and save them as a string in the database.
I'm building a ticketsystem with laravel. But when I remove a ticket the reactions don't go away?
This is my migration of the pivot table:
public function up()
{
Schema::create('reactions_ticket',function(Blueprint $table)
{
$table->integer('ticket_id')->unsigned();
$table->foreign('ticket_id')->references('id')->on('ticket')->onDelete('cascade');
$table->integer('reactions_id')->unsigned();
$table->foreign('reactions_id')->references('id')->on('reactions')->onDelete('cascade');
});
}
And this is my reaction table:
public function up()
{
Schema::create('reactions',function(Blueprint $table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->text('content');
$table->timestamps();
});
}
and my ticket table:
public function up()
{
Schema::create('ticket',function(Blueprint $table)
{
$table->increments('id');
$table->string('slug')->nullable();
$table->integer('ticketid')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('subject_id')->unsigned();
$table->foreign('subject_id')->references('id')->on('subject')->onDelete('cascade');
$table->integer('websites_id')->unsigned();
$table->foreign('websites_id')->references('id')->on('websites')->onDelete('cascade');
$table->integer('status_id')->unsigned();
$table->foreign('status_id')->references('id')->on('status')->onDelete('cascade');
$table->text('content');
$table->timestamps();
});
}
What am I doing wrong>?
I would always prefer to handle such actions by myself instead of let id be done by MySQL.
You could use laravels event-handler inside your Ticket model.
protected static function boot() {
parent::boot();
static::deleting(function($ticket) {
// delete related stuff ;)
$reaction_ids = $ticket->reactions()->lists('id');
Reaction::whereIn($reaction_ids)->delete();
});
}
So you still have (if you want/need) the advantage of softdelete and more controll.
You have a many to many join between reactions and tickets. Therefore a ticket can have many reactions and a reaction could have many tickets. If you delete a ticket I would not expect to have the reactions deleted because those reactions could be attached to other tickets that are not deleted.
What will be deleted are the entries in the pivot table for that ticket. If you wanted to clean up all reactions that no longer have a ticket attached, that would be a separate task, mysql won't cascade that for you.
Your table names are not standard, Btw. They should be tickets, reactions, and reaction_ticket for the pivot table.
I have following table
Schema::create('jokes_categories', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('is_active');
$table->timestamps();
});
Schema::create('jokes', function(Blueprint $table) {
$table->increments('id');
$table->string('content', 200)->unique();;
$table->enum('is_active', array('Y', 'N'));
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('jokes_categories');
$table->timestamps();
});
In the jokes table category_id is a foreign key and it has a one-to-many relationship with jokes_categories
In the model I have the following:
class Joke extends \Eloquent {
public static $rules = array();
// Don't forget to fill this array
protected $fillable = array();
public function JokesCategory(){
return $this->belongsTo('JokesCategory');
}
}
In the controller I have the following:
$jokes = Joke::all();
But it does not pull through joke_categories.name (I was under the impression that the model definition will directly help to pull related models)
What could be the solution?
Your query is just on the Joke table.
You could eagerload the categories ie.
$jokes = Joke::with('JokesCategory')->get();
See docs: http://laravel.com/docs/eloquent#eager-loading
The convention is actually camel case instead of pascal case, otherwise Laravel doesn't seem to automatically load the relationships. I made the same mistake and couldn't figure out why my relationships where not loading automatically.
public function jokesCategory()