laravel Pivot table for Many to Many relation without laravel convention - php

I have 2 model user and team, every team can have multiple users and each user can be in any team , so I wanna make a many to many relation.
I'm trying to customize something , I don't wanna use the laravel convention for pivot table.
Here is my User Migration:
class CreateUsersTable extends Migration
{
protected $collection = "table_users";
public function up()
{
Schema::create( $this->collection
, function (Blueprint $table) {
$table->string('_id');
$table->string('username')->unique();
$table->string('password');
}
}
}
And here is my Team Migration :
class CreateTeamTable extends Migration
{
protected $collection = "table_team";
public function up()
{
Schema::create( $this->collection
, function (Blueprint $table) {
$table->string('_id');
$table->string('name')->unique();
}
}
}
So my problem is when I want to create method for the relation in User Model and Team Model.
in Team Model :
public function users()
{
return $this->belongsToMany(User::class, '??', '??' , '??'); // what should I insert in '??'
}
in User Model :
public function teams()
{
return $this->belongsToMany(Team::class, '??', '??' , '??'); // what should I insert in '??'
}
And also how to create Pivot table without using any convention:
pivot table that I created so far:
class CreateUsersTeamTable extends Migration
{
protected $collection = "team_user_pivot";
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create( $this->collection
, function (Blueprint $table) {
$table->id();
$table->string('??'); // please help me to fill this field
$table->string('??'); // please help me to fill this field
$table->timestamps();
});
}
There are '??' in User Model and Team model and Pivot table . help me to fill up each of them

It's not quite as simple as filling in the fields, as you're using a string for the foreign key as well as not follwing the standard namig conventions.
create_team_user_pivot
protected $collection = "team_user_pivot";
public function up()
{
Schema::create($this->collection, function (Blueprint $table) {
$table->id();
$table->string('team__id')->references('_id')->on('teams');
$table->string('user__id')->references('_id')->on('users');
$table->timestamps();
});
}
You also need to edit the models:
User
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
public $table = 'table_users';
public $incrementing = false;
public $keyType = 'string';
protected $primaryKey = '_id';
protected $fillable = [
"_id",
"username",
"password"
];
public function teams()
{
return $this->belongsToMany(Team::class, 'team_user_pivot', 'user__id', 'team__id');
}
}
Team
class Team extends Model
{
use HasFactory;
public $table = 'table_teams';
public $incrementing = false;
public $keyType = 'string';
protected $primaryKey = '_id';
protected $guarded = [];
public function users()
{
return $this->belongsToMany(User::class, 'team_user_pivot', 'team__id', 'user__id');
}
}

you have to create another model with migration
class UserTeam extends Model
{
public $timestamps = false;
protected $table = 'user_has_team';
protected $fillable = ['user_id', 'team_id'];
}
in your team model
public function users()
{
return $this->belongsToMany(User::class, 'user_has_team', 'user_id', 'team_id');
}
in your user model
public function teams()
{
return $this->belongsToMany(Team::class, 'user_has_team', 'team_id', 'user_id');
}

Related

Laravel: user id is not added as Foreignkey

I want that a user can create e.g. a football club. When the logged in user creates the club (with an Input-field) the foreignkey should automatically appear in the table of the club.
User
User Modell
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
public function wgGroup()
{
return $this->hasOne('WgGroup','user_id');
}
}
WgGroup e.g. for example to create a club
WgGroup Controller
class WGController extends Controller
{
public function dashboard()
{
return view('verified.dashboard');
}
public function createWG(Request $request)
{
$wg = new WgGroup();
$wg->wg_name = $request->wg_name;
$wg->user_id = User::find($request['id']);
$wg->save();
if($wg != null){
return redirect()->back()->with(session()->flash('alert-success', 'Your wg are createt'));
}
return redirect()->back()->with(session()->flash('alert-danger', 'Something went wrong!'));
}
}
WgGrup Model
class WgGroup extends Model
{
use HasFactory;
protected $table = 'wg_groups';
protected $fillable = [
'wg_name', 'user_id'
];
public function user() {
return $this->belongsTo('User');
}
}
WgGroup Database
class CreateWgGroups extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('wg_groups', function (Blueprint $table) {
$table->id();
$table->string('wg_name');
$table->foreignId('user_id')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('wg_groups');
}
}
I don't know exactly why the FK user_id is not added directly to the database.
public function user() {
return $this->belongsTo('User');
}
I thought through this function would happen.

Doctrine\DBAL\Schema\SchemaException: There is no column with name 'deleted_at' on table 'users'

I built an API (back: Laravel & front: angular) and I would like to test my API.
I'm a beginner on Laravel and i've got problems when I want to do some integration test. Indeed, I tried this little test:
class userTest extends TestCase
{
public function testExample()
{
$response = $this->getJson('/api/listUsers');
$response->assertStatus(200);
}
}
and I always have this error:
Doctrine\DBAL\Schema\SchemaException: There is no column with name 'deleted_at' on table 'users'.
While yet 'deleted_at' exist in my table 'users, so I don't understand, I searched on internet but no one got this error when running the phpunit command.
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('firstname');
$table->string('lastname');
$table->string('email')->unique();
$table->string('password');
$table->date('date_of_birth');
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
}
public function down()
{
Schema::dropIfExists('users');
Schema::table('users', function (Blueprint $table) {
$table->dropSoftDeletes();
});
}
}
And my User class:
class User extends Authenticatable implements JWTSubject
{
// 1. Dépendances
use SoftDeletes;
use Notifiable;
// 2. properties
protected $appends = ['fullname', 'age'];
protected $fillable = [
'firstname', 'lastname', 'email', 'password','date_of_birth'
];
protected $hidden = [
'password', 'remember_token', 'created_at', 'updated_at', 'deleted_at', 'pivot',
];
protected $table = 'users';
// 3. getters & setters
public function setPasswordAttribute($password)
{
$this->attributes['password'] = bcrypt($password);
}
public function getFullNameAttribute() {
return ucfirst($this->firstname) . ' ' . ucfirst($this->lastname);
}
public function getAgeAttribute()
{
return Carbon::parse($this->attributes['date_of_birth'])->age;
}
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}
// 4. other methods
public function projects()
{
return $this->belongsToMany(Project::class);
}
}
Can I have some help pls ??
Try running below commands.
php artisan cache:clear
php artisan config:clear
php artisan config:cache
Also, Try to remove the deleted_at column from $hidden attribute.

Eloquent relationships: cloumn doesn't exist

I'm new to Laravel and am having a bit of a hard time cracking how relationships work. I'm building a simple e-commerce application, where each user has some orders, and order has one or many sub-orders, and each sub-order is linked to only one item (please don't comment on my scheme yet; for now I just need to figure out Eloquent and will be doing refactoring later :) ).
Following are my models:
class Order extends Model
{
//timestamp
protected $created_at;
public function sub_orders() {
return $this->hasMany('App\SubOrder');
}
public function user() {
return $this->belongsTo('App\User');
}
}
class SubOrder extends Model
{
protected $fillable = array('delivery_date', 'quantity', 'total_price', 'delivery_status');
public function item() {
return $this->hasOne('App\Item');
}
public function order() {
return $this->belongsTo('App\Order');
}
}
class Item extends Model
{
//note - slug is kind of categorization and is common to many items
protected $fillable = array('sku', 'name', 'slug', 'unit_price');
}
And here are the migrations:
class CreateOrdersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->timestamp('created_at');
//foreign keys
$table->unsignedInteger('user_id')->after('id');
$table->foreign('user_id')->references('id')->on('users') ->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('orders');
}
}
class CreateSubOrdersTable extends Migration
{
public function up()
{
Schema::create('sub_orders', function (Blueprint $table) {
$table->increments('id');
$table->date('delivery_date');
$table->decimal('quantity', 5, 2);
$table->decimal('total_price', 7, 2);
$table->enum('delivery_status', ['pending_from_farmer', 'ready_for_customer', 'out_for_delivery', 'delivered']);
//foreign keys
$table->unsignedInteger('order_id')->after('id');
$table->foreign('order_id')->references('id')->on('orders') ->onDelete('cascade');
$table->unsignedInteger('item_id')->after('order_id');
$table->foreign('item_id')->references('id')->on('items') ->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('sub_orders');
}
}
class CreateItemsTable extends Migration
{
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->increments('id');
$table->string('sku')->unique();
$table->string('name');
$table->string('slug');
$table->decimal('unit_price', 5, 2);
});
}
public function down()
{
Schema::dropIfExists('items');
}
}
The problematic expression is why I write App\Order::all()[0]->sub_orders[0]->item in my web.php and get the following error:
SQLSTATE[42703]: Undefined column: 7 ERROR: column items.sub_order_id does not exist
LINE 1: select * from "items" where "items"."sub_order_id" = $1 and ...
^ (SQL: select * from "items" where "items"."sub_order_id" = 1 and "items"."sub_order_id" is not null limit 1)
I don't understand why it's looking for sub_order_id in the items table. And what's the right way to go about doing it?
Overall: define the 1-to-1 relationship using hasOne or belongsTo will affect the target table where Laravel find the foreign key. hasOne assume there is a my_model_id in target table.And belongsTo assume there is a target_model_id in my table.
class SubOrder extends Model
{
public function item() {
return $this->hasOne('App\Item', 'id', 'item_id');
}
}
or
class SubOrder extends Model
{
public function item() {
return $this-> belongsTo('App\Item');
}
}
According to Laravel Doc
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Eloquent determines the foreign key of the relationship based on the model name. In the above case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:
$this->hasOne('App\Phone', 'foreign_key', 'local_key');
Or Defining The Inverse Of The Relationship
class Phone extends Model
{
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
In the example above, Eloquent will try to match the user_id from the Phone model to an id on the User model.
Your SubOrder item has relationship of type OneToOne (hasOne is bidirectional) with an Item.
So Eloquent expects to have sub_order_id in the items table.
So the solution is to define the inverse of this relationship (belongsTo) in the Item model

Laravel - how to change table in orWhere method?

I want to do something like this:
$posts= Status::where('users_id',$user->id)->orWhere(DB::table('user_status_share.user_id', $user->id))->orderBy('created_at', 'DESC')->get();
But I'm getting an error: strtolower() expects parameter 1 to be string, object given - how can I change the table in "orWhere" method? Is this possible? If not - how to use 2 tables in one query?
Schema (Status):
public function up()
{
Schema::create('users_status', function (Blueprint $table) {
$table->increments('id')->unique();
$table->longText('status_text');
$table->integer('users_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users_status');
}
Schema (StatusShare):
public function up()
{
Schema::create('user_status_share', function (Blueprint $table) {
$table->increments('id');
$table->integer('status_id');
$table->integer('user_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('user_status_share');
}
Model Status:
namespace App\Eloquent;
use Illuminate\Database\Eloquent\Model;
class Status extends Model
{
public $timestamps = true;
protected $table = 'users_status';
protected $guarded = ['id'];
public function comments()
{
return $this->hasMany(StatusComments::class);
}
public function likes()
{
return $this->hasMany(StatusLikes::class);
}
public function shares()
{
return $this->hasMany(StatusShare::class);
}
}
Model StatusShare:
<?php
namespace App\Eloquent;
use Illuminate\Database\Eloquent\Model;
class StatusShare extends Model
{
public $timestamps = true;
protected $table = 'user_status_share';
protected $guarded = ['id'];
public function status()
{
return $this->hasOne(Status::class);
}
}
I think you should try something like this
tweak it , i didnt test it
$posts = DB::table('status')->where('users_id',$user->id)->orWhere(function ($query) use ($user) {
$query->table('user_status_share')->where('user_id', $user->id);
})
->get();
can you share more informations because i have a feeling that these can be reached in a simple way using relations (show us database structure and relations in your models)

Eloquent eager loading doesn't work with my naming convention

I have been stuck for most of the day getting an empty array any time I eager loaded product images while requesting products in my controller in Laravel.
public function ProductImages() {
return $this->hasMany('App\ProductImage', 'product_id'); // this matches the Eloquent model
}
I changed my code to make the FK 'test' and suddenly it has started returning the appropriate data I want back. I put the FK back to product_id but again am back to an empty array. Below are My product Model ProductImages Model and the migrations for both with the call Im making in the controlelr
Product Model
class Product extends Model
{
protected $fillable = array('name', 'url_name', 'sku', 'description', 'short_description', 'enabled', 'track_inventory', 'stock_level', 'allow_backorder', 'updated_user_id' );
//protected $hidden = array('id');
// LINK THIS MODEL TO OUR DATABASE TABLE ---------------------------------
// Database table is not called my_products
protected $table = 'products';
// each product HAS many product images
public function ProductImages() {
return $this->hasMany('App\ProductImage', 'productId'); // this matches the Eloquent model
}
}
Product Images Model
class ProductImage extends Model
{
protected $fillable = array('name', 'description', 'path', 'sort_order', 'product_id');
// DEFINE RELATIONSHIPS --------------------------------------------------
// each attribute HAS one product
public function Product() {
return $this->belongsTo('App\Product', 'id'); // this matches the Eloquent model
}
}
Product Migration
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('url');
$table->string('sku');
$table->string('description');
$table->string('short_description');
$table->integer('enabled');
$table->integer('track_inventory');
$table->integer('stock_level');
$table->integer('allow_backorder');
$table->dateTime('updated_user_id');
$table->timestamps();
});
}
}
Product Images Migration
class CreateProductImagesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('product_images', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->string('path');
$table->integer('sort_order');
$table->integer('product_id')->unsigned();
$table->foreign('product_id')->references('id')->on('products');
$table->timestamps();
});
}
}
Product Controller Snippet
public function index()
{
//
$Products = Product::with('ProductImages','productTypes')->get();
//dd($Products);
return response()->json( $Products, 200);
}
If you could help me understand why this strange behavior is happening i would be very grateful.

Categories