why foreign key not get setted in laravel migrations - laravel

I made an exam-question relationship, every exam has less than 200 questions, but when I run migrations, I go to the PHPMyAdmin and I don't find the foreign key set, it's only a bigint(20) unsigned column and not linked to the exams table.
exam model
<?php
namespace App\Models;
use App\Models\Question;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Exam extends Model
{
use HasFactory;
protected $fillable = [
//
];
public function questions(){
return $this->hasMany(Question::class);
}
}
question model
<?php
namespace App\Models;
use App\Models\Exam;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
class Question extends Model
{
use HasFactory;
function exam(){
return $this->belongsTo(Exam::class);
}
}
exam migration
<?php
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateExamsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('exams', function (Blueprint $table) {
$table->id();
$table->string('examHash')->unique();
//..
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('exams');
}
}
questions migrations
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateQuestionsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('questions', function (Blueprint $table) {
$table->id();
$table->foreignId('exam_id')->constrained();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('questions');
}
}
I've tried to:
Use this
$table->foreign('exam_id')->references('id')->on('exams');
but
Key column 'exam_id' doesn't exist in table
EDIT:
it can be caused because my engine is not InnoDB, regularly I change the engine to InnoDB to create foreign keys

The method foreignId will only create an UNSIGNED BIGINT and not a foreign key constraint. To also create a constraint you need to call constrained() afterward.
Try this:
Schema::create('questions', function (Blueprint $table) {
$table->id();
$table->foreignId('exam_id')->constrained();
$table->timestamps();
});
You can also find more information in the documentation.

Try to add the constrained method when you define the foreign key in question's migration, change:
$table->foreignId('exam_id');
to:
$table->foreignId('exam_id')->constrained();

the problem as I've mentioned in the question is in the engine. so I wrote
$table->engine = 'InnoDB';
in both of question and exam tables...

Related

How to reflect the data into server database?

I am using laravel framework and firebase-database,i am using laravel-firebase-sync package which is responsible for syncing the data to firebase and it's allows to use Eloquent queries upto this part is working fine,i created two migrations and models (User.php and Books.php).
when i hit user registration api the data is being stored in the firebase database ,when i create book(one to many relationships to the users table) the data is being stored in my local-DB(mysql) and it's not reflecting into the firebase,can you suggest how to sync the relations data into firebase
createBooksTable
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateBooksTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('books');
}
}
Books.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Mpociot\Firebase\SyncsWithFirebase;
class Books extends Model
{
//
use SyncsWithFirebase;
public function users(){
return $this->hasMany(User::class);
}
}
controller
public function createBook(Request $request){
Books::insert(['name' => $request->name,
'user_id' => $request->user_id
]);
return response()->json(['done']);
}

Get attribute in model - laravel eloquent

In laravel i can getFirstNameAttribute in my products model and change the value but I'm create this column "priceArray" and i can not get attributes because The first letter in the second word is capital letters and model can not found this column.
public function getPriceArrayAttribute($value)
{
return 'test';
}
Its not work and can not get "priceArray" column
This is my migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->string('price')->nullable();
$table->string('priceArray')->nullable();
$table->text('items')->nullable();
$table->enum('status',['active','inactive','unavailable'])->default('inactive');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('products');
}
}
This is my product model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
/**
* Class Products
* #package App\Models
* #property Variants Variants
*/
class Products extends Model
{
use HasFactory;
protected $guarded=[];
protected $changePrice=0;
public function Insert($data)
{
return self::create($data);
}
public function getPriceArrayAttribute($value)
{
return 'test';
}
public function getPriceAttribute($value)
{
return ceil($value);
}
}
The getPriceAttribute is worked but getPriceArrayAttribute does not worked
I think you are trying to modify the priceArray value after it is retrieved from the database, the way you did with ceil() on the price attribute. The only way this works is if you change the column name to price_array. This is by far the simplest fix.
Migration
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('title')->nullable();
$table->string('price')->nullable();
$table->string('price_array')->nullable();
$table->text('items')->nullable();
$table->enum('status',['active','inactive','unavailable'])->default('inactive');
$table->timestamps();
});
Model
public function getPriceArrayAttribute($value)
{
return 'test';
}
You must follow Eloquent's rules: you use snake case for the attributes. The getPriceArrayAttribute accessor will automatically be called by Eloquent when you retrieve the value of the price_array attribute.
$table->string('price_array')->nullable();

Laravel API: How to get data from foreign key from different table

I currently want to make an API that will get all the lessons by its module_id. These are currently my codes:
Module Migration Table:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateModulesTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up() {
Schema::create('modules', function (Blueprint $table) {
$table->id();
$table->string('module_name');
$table->bigInteger('created_by')->unsigned()->nullable();
$table->bigInteger('updated_by')->unsigned()->nullable();
$table->timestamps();
});
Schema::table('modules', function(Blueprint $table) {
$table->foreign('created_by')->references('id')->on('admins');
$table->foreign('updated_by')->references('id')->on('admins');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down() {
Schema::dropIfExists('modules');
}
}
Lesson Migration Table:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateLessonTable extends Migration {
/**
* Run the migrations.
*
* #return void
*/
public function up() {
Schema::create('lesson', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->bigInteger('module_id')->unsigned();
$table->longText('content');
$table->bigInteger('created_by')->unsigned()->nullable();
$table->bigInteger('updated_by')->unsigned()->nullable();
$table->string('enabled')->nullable();
$table->string('position')->nullable();
$table->timestamps();
});
Schema::table('lesson', function(Blueprint $table) {
$table->foreign('module_id')->references('id')->on('modules');
$table->foreign('created_by')->references('id')->on('admins');
$table->foreign('updated_by')->references('id')->on('admins');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down() {
Schema::dropIfExists('lesson');
}
}
And this is the GetLessonByModule controller of that API I want to make (getting all the lessons by its module_id):
<?php
namespace App\Http\Controllers;
use App\Models\Lesson;
use App\Models\Modules;
use Illuminate\Http\Request;
class GetLessonByModuleController extends Controller {
public function index() {
$lessons = Lesson::all();
return response($lessons,200);
}
}
The module_id and the ID in the modules table are currently connected as seen in the migration tables. I just don't know how to compose it in my Controller. I also don't know if I should make a new model. Any kind of help/suggestion is deeply appreciated. Thanks in advance.
You can do
<?php
namespace App\Http\Controllers;
use App\Models\Lesson;
use App\Models\Modules;
use Illuminate\Http\Request;
class GetLessonByModuleController extends Controller {
public function index(int $module_id) {
$lessons = Lesson::where('module_id', '=', $module_id)->get();
return response($lessons,200);
}
}
In your api.php there should be definition of the route:
Route::get('lessons-by-module/{module_id}', [\App\Http\Controllers::class, 'index']);
If it works for you and want to do it better, you can go fancy with Laravel routing explicit binding: https://laravel.com/docs/8.x/routing#explicit-binding

How Laravel defines name of the foreign-key as default in Model file?

I am new at Laravel and I am wondering how actually Laravel determines default foreign key name.
According to the Laravel document, it says "Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with _id".
Then, in this case↓, the default foreign key supposed to be named as info_id as the document says.
app/Models/Item.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Item extends Model
{
public function itemInfo()
{
return $this->hasOne(‘App\Models\ItemInfo’);
}
}
I just changed the name of infofunction as infooo THEN, no error happened. It do works...
What I expected was an error occurs because I thought Laravel would name the default foreign key as infooo_id and there is not such a column name in the tables.
It means Laravel does not determine the default foreign key name by the method name, doesn`t it?
Then what portion actually Laravel determine the default foreign key from?
These are the migration files of tables:
database/YYYY_MM_dd_hhiiss_create_items_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateItemsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create(‘items’, function (Blueprint $table) {
$table->increments(‘id’);
$table->string(‘name’);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists(‘items’);
}
}
YYYY_mm_dd_hhiiss_create_item_infos_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateItemInfosTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create(‘item_infos’, function (Blueprint $table) {
$table->increments(‘id’);
$table->integer(‘item_id’)->unsigned();
$table->string(‘genre’);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists(‘item_infos’);
}
}

Multi table inheritance in Laravel

I want just a simple example on how to have multi tables in database using Eloquent, for example :
I have a Model "Person", and there is 2 classes extending from this Model : Student and Teacher, and in database I don't want to have one table (persons), I want to have 2 tables (students and teachers).
How this is possible in Laravel (Eloquent), give me just the code of the three classes (Person, Student and Teacher).
Thanks a lot :)
Not tested but should work:
Docs
Person.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Person extends Model {
// ...
}
Student.php
<?php
namespace App;
class Student extends Person {
$table = 'students';
// ...
}
Teacher.php
<?php
namespace App;
class Teacher extends Person {
$table = 'teachers';
// ...
}
Migrations
You can create the desired migrations as usual with php artisan make:migration create_students_table --create=students. Then migrate with php artisan migrate
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateStudentsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
// ...
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('students');
}
}
EDIT
I don't know the background but maybe a trait is the better alternative.

Resources