Eloquent queries wrong table in many-to-many relationship - laravel-5.4

I'm having trouble with a many-to-many relationshop. When querying the relationship (tested in tinker) I'm getting an error message triggered by sql showing me a query on the wrong table.
My models:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Slideshow extends Model
{
public function pictures ()
{
return $this->hasMany(Picture::class);
}
}
namespace App;
use Illuminate\Database\Eloquent\Model;
class Picture extends Model
{
public function slideshows ()
{
return $this->belongsToMany(Slideshow::class,'slideshowpictures')->withPivot('order')->withTimestamps();
}
}
My migration for this relationship:
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateSlideshowpicturesMigration extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up ()
{
$tablename = 'slideshowpictures';
Schema::create($tablename, function (Blueprint $table)
{
$table->integer('slideshow_id')->unsigned();
$table->integer('picture_id')->unsigned();
$table->integer('order')->unsigned();
$table->timestamps();
});
Schema::table($tablename, function ($table)
{
$table->foreign('slideshow_id')->references('id')->on('slideshows')->onDelete('cascade');
$table->foreign('picture_id')->references('id')->on('pictures')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down ()
{
Schema::dropIfExists('slideshowpictures');
}
}
Now in tinker I get the following error:
>>> $slide =Slideshow::all()->first();
=> App\Slideshow {#751
id: 1,
name: "1",
occasion_id: 1,
created_at: "2017-09-16 19:01:59",
updated_at: "2017-09-16 19:01:59",
}
>>> $slide->pictures()->exists();
Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'pictures.slideshow_id' in 'where clause' (SQL: select exists(select * from `pictures` where `pictures`.`slideshow_id` = 1 and `pictures`.`slideshow_id` is not null) as `exists`)'
>>> $slide->pictures();
=> Illuminate\Database\Eloquent\Relations\HasMany {#830}
I could not yet find an answer and hope you can help me figure out why it is selecting from my pictures table and not the junction table which I created.

Related

Can't change data type in database using Laravel migration

I'm trying to change the data type (from string to boolean) of 5 columns in my database, but it's showing an error that i have no idea what is the meaning.
My migration is this:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ChangeFieldDataType extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->boolean('categoria_pneu')->change();
$table->boolean('categoria_dicas')->change();
$table->boolean('categoria_servicos')->change();
$table->boolean('categoria_dicas_gerais')->change();
$table->boolean('categoria_variados')->change();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('categoria_pneu');
$table->dropColumn('categoria_dicas');
$table->dropColumn('categoria_servicos');
$table->dropColumn('categoria_dicas_gerais');
$table->dropColumn('categoria_variados');
});
}
}
The erros that's showing, is this:
I don't know what is the meaning of the error, since i'm trying to change the type to BOOLEAN and not TINYINT (i don't actually know if it's the same...)

Eloquent foreign key

I am trying to make a 3 models relationship in Laravel 6 and Foreign keys won't work, becouse i get this error:
Illuminate/Database/QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'products.product_id' in 'where clause' (SQL: select * from `products` where `products`.`product_id` = 1 and `products`.`product_id` is not null limit 1)'
I have a 3 table (the tables are: users, cartItems, products) relationship . The foreign key that refers user's id into cartItems seamns to work, but the one that refers product's id into cartItems don't .
The cartItems table migration:
Schema::create('cart_items', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('product_id');
$table->timestamps();
$table->foreign('product_id')->references('id')->on('products');
});
The products table migraton:
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('productName');
$table->text('description');
$table->integer('price');
$table->string('image');
$table->timestamps();
});
The cartItem model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class cartItem extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
public function product() {
return $this->hasOne(Product::class, 'product_id');
}
}
The product model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $guarded = [];
public function cartItem() {
return $this->belongsToMany(Product::class);
}
}
The user model:
<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function cartItems() {
return $this->hasMany(cartItem::class);
}
}
$table->foreign('product_id')->references('id')->on('products');
expects the products table to be created already. Migrations run in filename order, so make sure your products table migration has an earlier "date" stamp than the cart_items table migration.
If you are specifying xxxxx_id columns in the cartItems table, then cartItem is the child model, not the parent. Otherwise you might need to rethink your relationships.
To fix as-is (and leave the migration the same), change your Eloquent relationships to:
// Product.php
public function cartItems() {
return $this->hasMany(cartItem::class);
}
and its inverse:
// cartItem.php
public function product() {
return $this->belongsTo(Product::class);
}

SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value in Laravel 6

Here, I'm trying to to insert the data in the database but for some reason I am not able to insert the data in the database. This is the error:
SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value (SQL: insert into stages (code, name, description, updated_at, created_at) values (32, dfs, vc, 2020-04-14 06:02:57, 2020-04-14 06:02:57))"
My code are here:
StageController.php
<?php
namespace App\Sys\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Sys\Model\Stage;
class StageController extends Controller
{
public function index(Request $request)
{
$per_page = $request->per_page ? $request->per_page : 5;
$sort_by = $request->sort_by;
$order_by = $request->order_by;
return response()->json(['stages' => Stage::orderBy($sort_by, $order_by)->paginate($per_page)],200);
}
public function store(Request $request)
{
$location= Stage::create([
'code' =>$request->code,
'name' =>$request->name,
'description' =>$request->description
]);
return response()->json(['stage'=>$stage],200);
}
public function show($id)
{
$stages = Stage::where('code','LIKE', "%$id%")->orWhere('name','LIKE', "%$id%")->orWhere('description', 'LIKE', "%$id%")->paginate();
return response()->json(['stages' => $stages],200);
}
public function update(Request $request, $id)
{
$stage = Stage::find($id);
$stage->code = $request->code;
$stage->name = $request->name;
$stage->description = $request->description;
$stage->save();
return response()->json(['stage'=>$stage], 200);
}
public function destroy($id)
{
$stage = Stage::where('id', $id)->delete();
return response()->json(['stage'=>$stage],200);
}
public function deleteAll(Request $request){
Stage::whereIn('id', $request->stages)->delete();
return response()->json(['message', 'Records Deleted Successfully'], 200);
}
}
Stage.php
<?php
namespace App\Sys\Model;
use Illuminate\Database\Eloquent\Model;
class Stage extends Model
{
protected $guarded = [];
}
My migration file:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateStagesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('stages', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('original_id',36)->default('0')->index();
$table->string('code',10)->index()->nullable();
$table->string('name',100);
$table->string('description',200)->nullable();
$table->char('created_by',36)->index();
$table->char('edited_by',36)->index()->nullable();
$table->timestamps();
$table->foreign('created_by')->references('id')->on('users');
$table->foreign('edited_by')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('stages');
}
}
In my case i didn't add that field into fillable in my Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['name'];
}
For laravel 5.6+ you can use Str::uuid() to generate the uuid string;
use Illuminate\Support\Str;
...
public function store(Request $request)
{
$uuid = Str::uuid()->toString();
$location= Stage::create([
'id' => $uuid,
'code' =>$request->code,
'name' =>$request->name,
'description' =>$request->description
]);
return response()->json(['stage'=>$stage],200);
}
For below laravel 5.6, you can use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\Uuid;
...
public function store(Request $request)
{
$uuid = Uuid::uuid1()->toString();
...
return response()->json(['stage'=>$stage],200);
}
Or you can write an boot method for generating uuid to creating, Eloquent will automatically set id=uuid for every create method. If there are many models with primary key uuid, you can write a trait and use this trait in each models.
use Illuminate\Support\Str;
...
class Stage extends Model
{
/**
* Boot function from laravel.
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->{$model->getKeyName()} = Str::uuid()->toString();
});
}
}

Laravel 5 - Eloquent relationship returning an empty collection

I'm having trouble with a Laravel 5 relationship. I have 2 models Crew and Event with the corresponding tables crews and events. Crews have many events, and events have one crew. I set up my models and migration as follows:
Schema:
//Crews
Schema::connection('scheduling')->create('crews', function ($table) {
$table->increments('id');
$table->text('name');
$table->boolean('solo');
$table->boolean('active');
$table->text('phone');
});
//Events
Schema::connection('scheduling')->create('events', function ($table) {
$table->increments('id');
// ...
$table->integer('crew_id')->unsigned();
$table->foreign('crew_id')->references('id')->on('crews');
$table->text('notes');
// ...
$table->timestamps();
});
Models:
namespace App\Models\Scheduling;
use Illuminate\Database\Eloquent\Model;
class Crew extends Model {
public $connection = "scheduling";
public $table = "crews";
public function events() {
return $this->hasMany('App\Models\Scheduling\Event', 'id', 'crew_id');
}
public static function active() {
return Crew::where('active', 1)->get();
}
}
namespace App\Models\Scheduling;
use Illuminate\Database\Eloquent\Model;
class Event extends Model {
public $connection = "scheduling";
public $table = "events";
public function crew() {
return $this->belongsTo('App\Models\Scheduling\Crew', 'crew_id', 'id');
}
}
If I run Crew::find(102)->events; I end up with an empty collection.
If I run Events::where('crew_id', 102)->get(); I end up with the list of events I expected.
Any idea what I'm doing wrong here?
Your definition of events relation is invalid - you pass the arguments in wrong order.
Replace:
return $this->hasMany('App\Models\Scheduling\Event', 'id', 'crew_id');
with
return $this->hasMany('App\Models\Scheduling\Event', 'crew_id', 'id');
or simply
return $this->hasMany('App\Models\Scheduling\Event');
as you are using the default values for the column names, so no need to pass them to the relation definition.

Laravel seeding tables in second database

connection('mysql2') is my (working) second database connection.
When I migrate first, connection('mysql2') is working like expected, the table is created.
Schema::connection('mysql2')->create('brands', function(Blueprint $table)
{
//...
});
But when I try to seed tables in my second database:
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
use App\Brands;
class DatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
Model::unguard();
$this->call('BrandsTableSeeder');
$this->command->info("Brands table seeded.");
}
}
class BrandsTableSeeder extends Seeder
{
public function run()
{
DB::connection('mysql2')->table('brands')->delete();
Brands::connection('mysql2')->create(['brand' => 'test']);
}
}
I got:
[BadMethodCallException]
Call to undefined method Illuminate\Database\Query\Builder::connection()
Problem with your code is you have used Connection() method with Eloquent(not DB), Eloquent doesn't have connection() method.
You can use on() method with model(Eloquent) to specify connection
$user = User::on('mysql2')->create(['brand' => 'test']);
reference http://laravel.com/docs/4.2/eloquent#basic-usage
or
instead of writing on('mysql2') everywhere
you can write following code in model
protected $connection = 'mysql2';
and now seed is written as
class BrandsTableSeeder extends Seeder
{
public function run()
{
Brands::truncate();
Brands::create(['brand' => 'test']);
}
}