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
Related
I'm using Laravel Framework; I have multiple connected tables,
User Schema Table :
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();
});
Article Schema Table :
Schema::create('articles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string("title");
$table->string("slug")->unique();
$table->text("cover");
$table->text("body");
$table->boolean("status")->default(1);
$table->timestamps();
});
Comment Schema Table :
Schema::create('comments', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger("user_id");
$table->foreign("user_id")->references("id")->on("users")->onDelete('cascade');
$table->unsignedBigInteger("article_id");
$table->foreign("article_id")->references("id")->on("articles")->onDelete('cascade');
$table->text("comment");
$table->bigInteger("level");
$table->boolean("status")->default(0);
$table->timestamps();
});
In the comments table I have this important code:
$table->unsignedBigInteger("user_id");
$table->foreign("user_id")->references("id")->on("users")->onDelete('cascade');
$table->unsignedBigInteger("article_id");
$table->foreign("article_id")->references("id")->on("articles")->onDelete('cascade');
I want to when I delete an article or user, I would like to have their comments deleted when a user or an article is deleted, But this is a mistake in the SQL Server database.
Error Form SQL Server Database:
enter image description here
When I removed this method
->onDelete('cascade');
The error disappears.
I definitely need to have the corresponding method. Can anyone guide me to solve this problem?
Use a delete observer instead, on delete cascade is not the best thing to do.
Define the relationship in User model:
/**
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function articles()
{
return $this->hasMany(Article::class, 'user_id');
}
Then implement the boot method to observe the deletion of a record
protected static function boot() {
parent::boot();
static::deleting(function($user) {
$user->articles()->delete();
});
}
You can loop on articles comments in the same method or do the same thing you did here with Article and Comment models
Read more about observers here https://laravel.com/docs/5.8/eloquent#observers
It seems that you are using cascade on delete even for the user who access it. I don't think you need to delete the list even if the user who is not the creator but only have access to it. So update following
Change
$table->foreign("user_id")->references("id")->on("users")->onDelete('cascade');
to
$table->foreign("user_id")->references("id")->on("users")->onDelete('no action');
I'm developing a practice project where I have 2 tables. An article table with heading and text and a user table. Now I want an admin (which I created in the database before) to create additional Article Categories. Does anyone have an idea how I can link my tables or my models now ? I've only been working with Laravel for a week now and don't quite look through it yet.
That are my tables :
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('heading',80);
$table->string('clubchoose')->default('DEFAULT');
$table->text('text');
$table->timestamps();
$table->unsignedInteger('author')->nullable();
$table->foreign('author')->references('id')->on('users');
$table->string('image')->nullable();
});
}
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->Increments('id');
$table->boolean('isAdmin')->default(false);
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
So in order to achieve that, you first need to create your categories model/controller/table:
php artisan make:model Category -m //-m flag creates migration automatically
php artisan make:controller CategoryController --reosource //--resource flag creates a CRUD controller.
After that, inside your categories table, add column article_id (and other fields you want):
public function up()
{
Schema::table('categories', function (Blueprint $table) {
// ...
$table->integer('article_id')->nullable();
});
}
After that, you need to alter your articles table by adding category_id column. To do that, create a new migration to add that just one column:
php artisan make:migration add_category_id_to_articles_table --table==articles
Inside that migration, add this:
public function up()
{
Schema::table('articles', function (Blueprint $table) {
$table->integer('category_id')->nullable();
});
}
Now that you have migrations set up, you need to set up relations. Inside your Article model, add this relation:
public function category(){
return $this->belongsTo('App\Category');
}
So an article will belong to category. For the categories, as they will have more than one article, add this relation:
public function articles(){
return $this->hasMany('App\Article');
}
So now, you have everything set up. Run migrations, and add some categories and test things out. Let me know if you have any errors or troubles.
EDIT:
If you want only an admin to add new categories, you could create a button that is only visible for admins. Something like this:
#if(Auth->user()->role == 'admin'){
//show button
#endif
I need to make a relationship between User and Subscription table.
The user who registers gets a default free user and sees 1 an offer.
If silver see 8 offers, gold 15, platinum 20.
I made a relationship between user and subscription tables with a pivot table subscription_user.
The first question is whether I made a mistake somewhere in relation the model?
The second question is how to return only one offers by default, or if you subscribe to 8 offers (silver), 15 (gold), 20 (platinum) and in which controller?
User table:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('subscription')->default('free');
$table->rememberToken();
$table->timestamps();
});
Subscription table:
Schema::create('subscriptions', function (Blueprint $table) {
$table->increments('id');
$table->string('subscription');
$table->integer('offers');
$table->timestamps();
});
Sabscription_user table:
Schema::create('subscription_users', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->index(); //user table
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); //foreign key relation
$table->integer('subscription_id')->unsigned()->index();
$table->foreign('subscription_id')->references('id')->on('subscriptions')->onDelete('cascade'); //foreign key relation
});
Subscription model:
class Subscription extends Model
{
public function users() {
return $this->belongsToMany('App\User');
}
}
User model:
public function subscriptions(){
return $this->belongsToMany('App\Subscription');
}
Is everything connected as it should be for many to many relationship?
In which controller I can get information about offers?
By convention the pivot table is named singular so you will need to specify by adding a second argument. I like to include all the arguments so there is no guessing anyway.
public function subscriptions()
{
return $this->belongsToMany("App\Subscription", 'subscription_users', 'user_id', 'subscription_id', 'id', 'id');
}
public function users()
{
return $this->belongsToMany("App\User", 'subscription_users', 'subscription_id', 'user_id', 'id', 'id');
}
Yes you should use a controller but it depends on where you are trying to display this. I imagine you will need to display the current subscriptions somewhere as well as add and remove.
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 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.