How to implement a combined cross and inner joins in Laravel? - php

I have defined 3 tables in Laravel as follow:
Schema::create('locales', function (Blueprint $table) {
$table->string('id', 2);
$table->string('name', 5000);
$table->timestamps();
$table->primary('id');
});
Schema::create('i18n_keys', function (Blueprint $table) {
$table->string('id', 255);
$table->timestamps();
$table->primary('id');
});
Schema::create('i18ns', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('key', 255);
$table->string('locale', 2);
$table->string('translation', 5000)->nullable();
$table->timestamps();
$table->foreign('key')->references('id')->on('i18n_keys')->onDelete('cascade')->onUpdate('cascade');
$table->foreign('locale')->references('id')->on('locales')->onDelete('cascade')->onUpdate('cascade');
$table->unique(array('key', 'locale'));
});
Now the question is how can I implement the following SELECT statement in Laravel programmatically. I mean without running the SQL statement directly.
SELECT `il`.`key`, `il`.`locale`, `in`.`translation` FROM
(SELECT `ik`.`id` AS `key`, `lo`.`id` AS `locale` FROM `i18n_keys` as `ik` CROSS JOIN `locales` as `lo`) AS `il`
left join `i18ns` as `in`
ON `in`.`key` = `il`.`key`
and `in`.`locale` = `il`.`locale`;
The aim is to extract the keys that they don't have a translation yet. But I like to do this with query builder or eloquent or something similar rather than pass the query directly. Is there any way?

You can try this code:
use App\Models\I18nKey;
$ik = I18nKey::crossJoin('locales as lo')
->select('i18n_keys.id AS key', 'lo.id AS locale');
$res = \DB::table(\DB::raw("({$ik->toSql()}) AS il"))
->mergeBindings($ik->getQuery())
->leftjoin('i18ns as in',function($join){
$join->on('in.key', '=', 'il.key')
->whereColumn('in.locale', 'il.locale');
})->select('il.key','il.locale','in.translation')->get();

Related

Refactor database schema on migration

This is my initial migration
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->String('customer_name');
$table->String('customer_phone');
//others
});
Now, the easy time ended and now I have to move name and phone to customer table. This is my create customer migration. I don't know where to do this operation so I just throw all in the migration.
Schema::create('customers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('phone', 15);
//others
});
$users = DB::table('orders')->select(['customer_name', 'customer_phone'])->distinct()->get();
foreach ($users as $user) {
$attr['name'] = $user->customer_name;
$attr['phone'] = $user->customer_phone;
Customer::create($attr);
}
And alter order migration
Schema::table('orders', function (Blueprint $table) {
$table->unsignedBigInteger('customer_id')->nullable()->after('id');
$table->foreign('customer_id')->references('id')->on('customers');
});
Now I'm stuck with empty customer_id. I have no clue what to do next, except manually insert it by referring to two table, which can take too much time to update hundreds of rows.
Try use this statement on up function.
DB::statement("UPDATE `orders` o SET `customer_id` = (SELECT `id` FROM `customers` WHERE `name` = o.customer_name AND `phone` = o.customer_phone)");
And you might want to drop those two column. Throw this too.
Schema::table('orders', function (Blueprint $table) {
$table->dropColumn(['customer_name', 'customer_phone']);
});

Change Primary ID in laravel Migration

I'm creating a table where I want to use the ID from this table "menu_items" to be added in another table
Table one: menu_items
Schema::create('menu_items', function (Blueprint $table) {
$table->id('menu_level_item_id');
$table->timestamps();
$table->string('menu_item_name');
$table->string('menu_item_desc');
Table 2 products
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_name');
$table->string('product_desc');
$table->integer('price');
$table->integer('menu_level_item_id');
$table->timestamps();
});
My aim of doing this is that I can then create a relationship between the 2 tables as they have the same key?
Is there a different approach I can take? Should I create a unique key when creating a menu item and then add this to the second table?
Thank you.
Basically Laravel Eloquent do the key handling. When you have two tables which both has as key the name id, this is not a problem. Name the keys in the relation table just like this
table1_id
table2_id
Laravel will handle this in Eloquent. You are also able to name the two columns in the relation table to what ever you want. You could define it for the relation in Eloquent. E.g.
public function otherModel () {
return $this->belongsToMany('App\Models\OtherModel', 'table_name', 'this_model_id', 'other_model_id');
}
Please have a look into:
Laravel Relationship Documentation
Schema::create('menu_items', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('menu_item_name');
$table->string('menu_item_desc');
table->timestamp();
});
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('product_name');
$table->string('product_desc');
$table->integer('price');
$table->unsignedBigInteger('menu_level_item_id');
$table->timestamps();
$table->foreign('menu_level_item_id')->references('id')->on('menu_items');
});

Select statement with group_concat not working when other columns are called in laravel

Hello my laravel code is
$productDetails = DB::table('products')
->select(DB::raw('products.name, GROUP_CONCAT(sizes.name) as sizesName'))
->join('subcategories', 'products.subcategories_id', '=', 'subcategories.id')
->join('size_categories', 'subcategories.categories_id', '=', 'size_categories.categories_id')
->join('sizes',function($join){
$join->on(DB::raw("FIND_IN_SET(sizes.id, size_categories.size_id)"),">",DB::raw("'0'"));
})
->where('products.id', $request->id)
->get();
This doesnt work, when i useproducts.name or any other column name in select statement
but when i use only group_concat inside Db::raw and nothing else, the query works.
So how do i fetch other columns?
Please help.
I am stuck on it for quite a while
The query i want is
select GROUP_CONCAT(sizes.name),`products`.`name`, `products`.`image`, `products`.`id`, `products`.`image_second`, `products`.`description`, `products`.`min_order`, `size_categories`.`size_id` from `products`
inner join `subcategories` on `products`.`subcategories_id` = `subcategories`.`id`
inner join `size_categories` on `subcategories`.`categories_id` = `size_categories`.`categories_id`
join sizes on (FIND_IN_SET(sizes.id,size_categories.size_id)>0) where `products`.`id` = '7'
Please note that the above query is working fine. I just cant make it in laravel to work. Only the group_concat part.
This is the screenshot from my database, when i dont use group_concat
Also the DISTINCT part is doing nothing there, please ignore it.
I was just trying that out
This is the migration of create_products_table
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('units_id');
$table->unsignedBigInteger('selections_id');
$table->unsignedBigInteger('subcategories_id');
$table->string('name');
$table->string('image');
$table->text('description');
$table->string('min_order');
$table->timestamps();
$table->index('units_id');
$table->index('selections_id');
$table->index('subcategories_id');
});
}
migration of create_subcategories_table
public function up()
{
Schema::create('subcategories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->unsignedBigInteger('categories_id');
$table->timestamps();
$table->index('categories_id');
});
}
data of size_categories table
public function up()
{
Schema::create('size_categories', function (Blueprint $table) {
$table->id();
$table->string('size_id');
$table->unsignedBigInteger('categories_id');
$table->timestamps();
$table->index('categories_id');
});
}
migration of categories table
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
migration of sizes table
public function up()
{
Schema::create('sizes', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
In sizes table data is in this form
id name
1 2m
2 3m
3 4m
First, you need to specify select columns separately. Like so:
->select(DB::raw('products.name'), DB::raw('GROUP_CONCAT(sizes.name) as sizesName'))
Next, since group concat is an aggregate column, you need to group the sizes, and product name since it's in the select list and it is not related to size.
->groupBy('size_categories.size_id', 'products.id') //edit after your comment. group by prodcuts.id to be able to select columns from products table.
So your final query should look like this:
$productDetails = DB::table('products')
->select(DB::raw('products.name'), DB::raw('GROUP_CONCAT(sizes.name) as sizesName'))
->join('subcategories', 'products.subcategories_id', '=', 'subcategories.id')
->join('size_categories', 'subcategories.categories_id', '=', 'size_categories.categories_id')
->join('sizes',function($join){
$join->on(DB::raw("FIND_IN_SET(sizes.id, size_categories.size_id)"),">",DB::raw("'0'"));
})
->where('products.id', 7)
->groupBy('size_categories.size_id', 'products.id')
->get();

Use two tables on a two-to-many relationship or use three tables with a pivot table

Basically, I have 2 tables in my database: Games and Teams.
Every Game must have 2 teams, so it's a two-to-many relationship.
Should I use 2 foreign keys in my Games table pointing to the 2 teams in the Teams table and have a one-to-many relationship, or use many-to-many relationship with a third table to link the games and teams table?
Im using Laravel 6.5 for the project, so I guess im using Eloquent to implement it.
Schema::create('games', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('team_a_id');
$table->foreign('team_a_id')->references('id')->on('teams')->onDelete('restrict');
$table->unsignedBigInteger('team_b_id');
$table->foreign('team_b_id')->references('id')->on('teams')->onDelete('restrict');
$table->unsignedInteger('team_a_score');
$table->unsignedInteger('team_b_score');
$table->string('status');
$table->boolean('finished');
});
Schema::create('teams', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('abbreviation');
$table->string('country');
$table->timestamps();
});
This are the two tables I have created by now, is this the correct way to implement it?
Use a Many to Many Relationship. In that case the Game Modal could have multiple Teams and vice-versa.
Hence the migrations would be like:
Schema::create('games', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('status');
$table->boolean('finished');
});
Schema::create('teams', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('abbreviation');
$table->string('country');
$table->timestamps();
});
Schema::create('game_team', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('game_id');
$table->integer('team_id');
$table->unsignedInteger('score');
$table->timestamps();
});

SQL Foreign Key General Error 1215 when creating migrations

I built two migrations:
public function up()
{
Schema::create('incidents', function (Blueprint $table) {
$table->increments('id');
$table->string('user_id');
$table->integer('incident_type_id')->unsigned();
$table->string('type');
$table->string('incident_reference');
$table->integer('incident_id');
$table->date('date');
$table->time('time');
$table->string('location');
$table->string('street');
$table->string('city');
$table->double('latitude', 10, 6);
$table->double('longitude', 10, 6);
$table->smallInteger('incident_archived')->default(0);
$table->timestamps();
});
}
and the other one:
public function up()
{
Schema::create('responders', function (Blueprint $table) {
$table->increments('id');
$table->string('user_id');
$table->string('responder_id');
$table->integer('incident_id');
$table->foreign('incident_id')->references('incident_id')->on('incidents');
$table->double('last_lat', 10, 6);
$table->double('last_lng', 10, 6);
$table->timestamps();
});
}
Now I want to use the incident_id as foreign key to the incidents table. But I get the error: Cannot add foreign key constraint. First I thought it is order of migrations that causes trouble, so the responder table would be created before the incident table. But this is not the case. So why am I blocked using incident_id as foreign key then?
Thank you

Categories