Query for tables with foreign key in codeigniter - codeigniter

I have 2 tables SjohlLBzads_products & SjohlLBzads_products_meta connected by column (post_id) as foreign key.
How do I create queries on multiple tables ?
Controller function which I have right now only makes query to a single table (SjohlLBzads_products).
I would like to display shipping column in SjohlLBzads_products_meta together with other columns from the current table.
public function index(){
$this->load->library('lib_pagination');
$pg_config['sql'] = "SELECT * from SjohlLBzads_products";
$pg_config['per_page'] = 50;
$data = $this->lib_pagination->create_pagination($pg_config);
$this->load->view("product_listing", $data);
Thanks!

Use a JOIN statement
$pg_config['sql'] = "SELECT * FROM SjohlLBzads_products
JOIN johlLBzads_products_meta
ON johlLBzads_products.post_id = johlLBzads_products_meta.post_id ";

Related

Laravel query builder select all except specific column

I have 2 tables with the same columns except the second table have one more column, this column is foreign key of the first;
what i want is to make union query;but for union the column must the same; so i want to select all column except for the column distinct;
The easy way is to provide in select all the same column:
$a = Table1::select(['column1', 'column2', 'etc...']);
$b = Table2::select(['column1', 'column2', 'etc...']);
and go with $a->union($b)->get();
but if i have too much column, i end up with so much column to provide in the select function; so what i want is to provide in the query the column that i don't want to retrieve;
i can put protected $hidden in the second table model but for some reason i need this distinct column on some other query;
Get all columns name by Schema::getColumnListing($table);
And computes the intersection of arrays
array_intersect($columnsName1, $columnsName2);
I haven't done it with 2 tables but I am using collections and rejecting certain columns on a similar project:-
$row = Table1::firstOrFail();
$exclude=['column_1', 'column_2'];
return collect(array_keys($row->getAttributes()))
->reject(function ($name) use ($row, $exclude) {
return in_array($name, $row->getHidden())
|| in_array($name, $exclude);
}
);

Laravel: How to get the latest record in group of records with where condition?

I have two tables which are named as students and cities. students table has a primary key which is related to the cities table.
Students table:
In the frontend, I would like to have the data of the cities table with these requirements:
The data of the students table must be grouped by city_id
If there are more than one records with the same city_id in the students table, select only the latest record of the group.
Search in the latest records and select only students who are inactive.
Here is the relationship function of the city model:
public function student()
{
return $this->hasOne(Student::class, 'city_id', 'id')->orderByDesc('id');
}
This is my controller function:
$data = City::whereHas('student', function($query){
$query->where('is_active', 0)
})->with('student')->get();
Expected result: Considering the sample data, the query must return nothing.
Current result: It returns the third row as there is an inactive student record in the second row. So in this case where condition doesn't work properly.
I can get expected result with this SQL query:
select *
from students s
where id = (select max(t2.id)
from students s2
where s.city_id = s2.city_id) AND is_active = '0';
How can I fix this logical error?
What about something like this?
public function inactiveStudent()
{
return $this->hasOne(Student::class, 'city_id', 'id')
->where('is_active', 0)
->orderByDesc('id');
}
$data = City::whereHas('inactive_student')
->with('inactive_student')
->get();
I'm not certain if it's inactive_student or inactiveStudent when you do the query.

SQLSTATE[42S22]: (SQL: select * from `categories` where `categories`.`departement_id` = 1 and `categories`.`departement_id` is not null)

I'm trying to select all categories of a specific departement.
class Test extends Controller
{
public function test(){
$depts=Departement::find(1)->categories;
foreach ($depts as $dept){
echo $dept->name;
}
return view('test');
}
}
A quick google search tells me SQLSTATE[42S22] is the code for 'Column not found'.
When you call Departement::find(1)->categories, Eloquent makes 2 queries
Get THE Department whe primary key is equal to 1
Get ALL the Categories where their 'departement_id' attribute is equal to 1
Given the query in your error
select * from `categories` where `categories`.`departement_id` = 1 and `categories`.`departement_id` is not null)
It's clear there is no departement_id column in your categories table.
If there's no departement_id column in your categories table
Either:
Add it in a migration.
Add it directly in the db if you do not work with migrations
If you want to make another column act as the foreign key
update your relationship method to reflect that.
https://laravel.com/docs/5.8/eloquent-relationships

laravel join fake table

I'm using datatables with server side processing in a Laravel project. My status column is integer, which is then formatted
->editColumn('status', function($orders) use ($statuses) {
return $statuses[$orders->status];
})
But this approach prevents status column from being used in search.
Is sthere a way to join query with fake table? Smth like this
->join('fake_status_table', 'production_orders.status', '=', 'fake_status_table.id')
Drafting two solutions
Solution #1
$orders= DB::table('production_orders')
->select(DB::raw("DECODE (status_id, 1, 'No started',
2, 'Running',
3, 'Done',
4, 'Defect')"))
solution #2
//create tamporary table
$status_table = DB::insert( DB::raw( "CREATE TEMPORARY TABLE statuses") );
$orders = \DB::table('production_requests')
// join it with drawing table
->join('statuses', 'production_requests.status', '=', 'statuses.id')
// Generate result
$result = Datatables::of($orders)->make(true);
// KILL TEMPORARY TABLE
$dropTable = DB::unprepared( DB::raw( "DROP TEMPORARY TABLE statuses" ) );
// RETURN RESULT
return $result;
Views is nothing but a temporary table..
But it was copy of the table itself.. You shall create a view according to your need.. If you want to have the view of your entire table .. then
CREATE VIEW test.v AS SELECT * FROM t;
Or even
CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
Then you shall return some data from the controller and construct the coloumn as we do usual in the datatables
Like this
Jquery :
$(document).ready(function() {
$('#example').DataTable();
} );
And then foreach for the table !!
Hope this helps you

Laravel: Improved pivot query

I am successfully querying following and it create 130 queries, I want to optimise it and reduce the number of queries, I have set upped the model and controllers following way.
Post Modal
class Post extends Eloquent {
public function Categories () {
return $this->belongsToMany('Category', 'category_post');
}
}
Category Modal
class Category extends Eloquent {
public function posts () {
return $this->belongsToMany('Post', 'category_post');
}
}
and in the Controller, I am using following query, what following query does is, querying the results based on category id.
$category = Category::with('posts')->where('id','=',$id)->paginate(10)->first();
return Response::json(array('category' => $category));
If anyone can give me a hand to optimise the query, would be really greatful.
You are wrong, it doesn't create 130 queries.
It will create the following 3 queries:
select count(*) as aggregate from `categories` where `id` = '5';
select * from `categories` where `id` = '5' limit 10 offset 0;
select `posts`.*, `posts_categories`.`category_id` as `pivot_category_id`, `posts_categories`.`post_id` as `pivot_post_id` from `posts` inner join `posts_categories` on `posts`.`id` = `posts_categories`.`post_id` where `posts_categories`.`category_id` in ('5');
But the question is what exactly you want to paginate. Now you paginate categories and it doesn't make much sense because there's only one category with selected $id.
What you probably want to get is:
$category = Category::where('id','=',$id)->first();
$posts = $category->posts()->paginate(10);
and this will again create 3 queries:
select * from `categories` where `id` = '5' limit 1;
select count(*) as aggregate from `posts` inner join `posts_categories` on `posts`.`id` = `posts_categories`.`post_id` where `posts_categories`.`category_id` = '5';
select `posts`.*, `posts_categories`.`category_id` as `pivot_category_id`, `posts_categories`.`post_id` as `pivot_post_id` from `posts` inner join `posts_categories` on `posts`.`id` = `posts_categories`.`post_id` where `posts_categories`.`category_id` = '5' limit 10 offset 0;
If you would like to improve it, you will probably need to not use Eloquent in this case and use join - but is it worth it? You would now need to manually paginate results without paginate() so it would probably won't be want you want to achieve.
EDIT
What you probably do is:
you get all posts that belongs to the category (but in fact you want to paginate only 10 of them)
for each post you want do display all categories it belongs to.
To lower number of queries you should use:
$category = Category::where('id','=',$id)->first();
$posts = $category->posts()->with('categories')->paginate(10);
and to display it you should use:
foreach ($posts as $p) {
echo $p->name.' '."<br />";
foreach ($p->categories as $c) {
echo $c->name."<br />";
}
}
It should lower your number queries to 4 from 130

Resources