Laravel multiple tables data filter - php

I am using Laravel 5 and I have 3 database tables projects, applications, users and their table structure are as followed:
Projects
Schema::create('projects', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description');
$table->char('status',1);
$table->timestamps();
});
Applications
Schema::create('applications', function (Blueprint $table) {
$table->increments('id');
$table->integer('project_id')->unsigned()->index();
$table->integer('user_id')->unsigned()->index();
$table->char('status');
$table->timestamps();
});
Users
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('role');
$table->string('name');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
Now, I wanted to perform a query to return all the projects where a specific user has not submitted any application to that project yet. So far this is the closest result I could get but it will return NULL in the projects.id for every projects that have no applications.
DB::table('projects')
->leftjoin('applications', 'applications.project_id', '=', 'projects.id')
->where('applications.user_id', '!=', $user->id)
->orWhereNull('applications.id')
->get();
Query Result
{
"total":1,
"per_page":5,
"current_page":1,
"last_page":1,
"next_page_url":null,
"prev_page_url":null,
"from":1,"to":1,
"data":[{
"id":null,
"name":"Project2",
"description":"Project2 detail",
"status":null,
"created_at":null,
"updated_at":null,
"project_id":null,
"user_id":null
}]
}
Does anyone has a solution to this?

DB::table('projects')
->leftjoin('applications', function($join){
$join->on('applications.project_id', '=', 'projects.id')
->where('applications.user_id', '=', $user->id);
})
->whereNull('applications.id')
->get();
Think that's what your looking for

I just figure out how to do this by using two different query and combined them together.
1) Select all user applications' project_id
$user_applications = Application::where('user_id', '=', $user->id)
->select('project_id as id')
->get();
2) Select the projects where the projects are not from previous list
$projects_not_applied = DB::table('projects')
->whereNotIn('id',$user_applications)
->get();
Query result (user has not apply for project 2):
[{
"id":"2",
"name":"Project2",
"description":"Project2 detail",
"status":"n",
"created_at":"2016-03-14 15:09:58",
"updated_at":"2016-03-14 15:09:58"
}]

Related

Column not found: 1054 Unknown column 'coin_user.symbol' in 'field list'

We have three models (user - currencies - balances) What should be the relationship of these tables, for example, I want to receive the amount of bitcoin currency of user
To do this, I have written the code as follows (according to the help I received from the previous question)
this is user table :
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->enum('type', [User::TYPE_ADMIN, User::TYPE_USER])->default(User::TYPE_USER);
$table->string('name');
$table->string('email')->unique()->nullable();
$table->timestamp('email_verified_at')->nullable();
$table->string('password')->nullable();
$table->timestamp('password_changed_at')->nullable();
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
coin table:
Schema::create('coins', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('symbol')->unique();
$table->decimal('buy_percent',6,4)->nullable();
$table->enum('buy_status' , ['active' , 'inactive'])->default('inactive');
$table->text('buy_description')->nullable();
$table->decimal('sell_percent',6,4)->nullable();
$table->enum('sell_status' , ['active' , 'inactive'])->default('inactive');
$table->text('sell_description')->nullable();
$table->timestamps();
});
and balances table. i include pivot table in this migration:
Schema::create('balances', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('coin_id');
$table->string('symbol');
$table->decimal('balance');
$table->timestamps();
});
Schema::create('coin_user', function(Blueprint $table)
{
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('coin_id');
$table->foreign('coin_id')->references('id')->on('coins')->onDelete('cascade');
});
And relationships are written that way:
in User model :
public function coins() {
return $this->belongsToMany(Coin::class)->withPivot(['symbol', 'balance']);
}
in Coin model :
public function users() {
return $this->belongsToMany(User::class)->withPivot(['symbol', 'balances']);
}
and Balance model :
public function coins()
{
return $this->belongsToMany(Coin::class , 'balances');
}
public function user()
{
$this->belongsToMany(User::class , 'balances');
}
when i run this code:
$coin = Coin::with('users')->get();
foreach ($coin as $coin) {
// $coin here is `BTC`, `ETH`, etc.
foreach ($coin->users as $user) {
// $user here is Bob, Mike, etc.
$user->pivot->balance; // 0.16, etc.
// Do whatever with `$coin` and `$user`
}
}
this error returned for me:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'coin_user.symbol' in 'field list' (SQL: select users.*, coin_user.coin_id as pivot_coin_id, coin_user.user_id as pivot_user_id, coin_user.symbol as pivot_symbol, coin_user.balances as pivot_balances from users inner join coin_user on users.id = coin_user.user_id where coin_user.coin_id in (1, 2, 3, 4) and users.deleted_at is null)
What is the problem? How can I access users' balances?
In Laravel, if two models are to have belongsToMany relationship, then a pivot table has to exist for the two models. The absence of a pivot table (assumed so as you did not provide any pivot table schema in your question) is the number one problem here.

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();

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

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();

Only show items that are not in other table laravel

I would like to only show the schools that are not favorited.
to get the ones favorited I use:
$favorite_schools = DB::table('favorite_schools')
->select('favorite_schools.*', 'schools.name')
->leftJoin('schools', 'schools.id', 'favorite_schools.school_id')
->get();
Schools table:
Schema::create('schools', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('active');
$table->timestamps();
});
Favorite_schools table:
Schema::create('favorite_schools', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('school_id');
$table->timestamps();
});
How can I only get the schools that have not been favorited yet?
You need to go the other way. Get the schools, and left join on the favorites table, then get the results that does not have a result in the favorite_schools table.
$favorite_schools = DB::table('schools')
->select('schools.name', 'schools.id')
->leftJoin('favorite_schools', 'schools.id', 'favorite_schools.school_id')
->whereNull('favorite_schools.school_id')
->get();
Add WhereNull('favorite_schools.school_id') to the query you use to get the favorite ones. that will give you the not favorite schools.
Good luck
a slightly different approach would be to use whereNotExists
usage would be something like this:
$schools = DB::table('schools')
->whereNotExists(function ($query) {
$query->select(DB::raw(1))
->from('favorite_schools')
->whereRaw('favorite_schools.school_id = school.id');
})
->get();

How to make selection query for join tables in laravel?

I have users and staffs tables. I want to display staff details after the login. The staff display will list the of staff with the same section with the user who login. For example, if Adam (section/seksyen=A) login, the staff list displayed are the staffs of section A.
How to make query for that in laravel?
table users:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->string('section');
$table->string('type');
});
}
table staffs:
public function up()
{
Schema::create('staffs', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('nama');
$table->string('emel')->unique();
$table->string('seksyen');
$table->string('jawatan');
$table->string('alamat');
$table->string('no kakitangan');
});
I have tried this query but doesn't work.
$data['data'] = DB::table('staffs')
->join('users', 'users.section', '=', 'staffs.seksyen')
->where('seksyen','=','Auth(section)')->get();
The right code to extract user login section name is :
$section = Auth::user()->section;
$data['data'] = DB::table('staffs')->where('section','=', $section)->get();

Categories