I know this is weird, but somehow I would like to know if it is possible, I am creating my own pagination, and I have been looking for eager loading with pagination but some say it is still not available.
//this query will get the record count
$qry_counter = LeadsModel::with('emails','contacts','create_by_name','sources');
//this query will get the data
$query = LeadsModel::with('emails','contacts','create_by_name','sources');
if(isset($inputs['page_no']) && isset($inputs['records_per_page']))
{
//setting pagination variables
$paginate_start_record = ($inputs['page_no'] - 1) * $inputs['records_per_page'];
//get the corresponding results based on the page and records per page
$query->skip($paginate_start_record)->take($inputs['records_per_page']);
}
//loop through condition
foreach($conditions as $condition)
{
$query->orWhere($condition[0],$condition[1],$condition[2]);
$qry_counter->orWhere($condition[0],$condition[1],$condition[2]);
}
$results_counter = $qry_counter->get()->count();
$results = $query->get();
Any advise on how to optimize this code? Will it be possible to get the total records count first and then it will also return the records based on the set with skip and take? Thanks in advance
Related
i see there are few methods we can apply pagination, an one of it is utilizing CI pagination library that generates links for us to navigate.
being main logic centered to
fetching limited data relevant to display
and iterate as move across pagination links.. here is my model logic without offset usage(for performance to use primary key id)
using limit, maxid of last run ,usertype; so next run should on rows greaterthan supplied id.
in controller say i am collecting results to data["results"] as
$data["results"] = $this->ressults_model->fetch_data($config["per_page"],$maxidvalue,$usertype);
in model.
public function fetch_data($limit,$maxid,$usertype) {
$date = date('Y-m-d');
$this->db->limit($limit);
$this->db->order_by('post_date', 'DESC');
$this->db->select('id,title');
if ($usertype == 1)
{$query = $this->db->get_where('titles',array('id >' => $id,'expiry_date >' => $date));}
else
{$query = $this->db->get_where('titles',array('id >' => $id,'expiry_date >' => $date,'visibility'=>'All'));}
if ($query->num_rows() > 0)
{ return $query->result(); }
return array();
}
challenge how to collect and pass the maxid recursively for pagination to work.
appreciate some pointers.
Thanks
Solved!
i have used session variable maxid that stores the max value and feeds the fetch_data method as parameter after every result display.
foreach ($data["results"] as $row) {
if ( $this->session->get_userdata('sessiondata')['maxid'] > $row->id)
$this->session->unset_userdata('maxid');
$this->session->set_userdata('maxid',$row->id);
echo "new value".$this->session->get_userdata('sessiondata')['maxid'];
}
please post if you have any better solution to solve this.
Thanks!
I'm new to Doctrine, and I just could not find a way to get the total number of results when using limit with Criteria (via setMaxResults function) in the EntityRepository::matching method.
In my repository (not an extend of EntityRepository), I'm using the following (I know this is not the optimal code, it is used just to learn Doctrine):
public function getAll($query = null) {
if ($query instanceof Criteria) {
$users = $this->em->getRepository('App\Entities\User')->matching($query)->toArray();
} else {
$users = $this->em->getRepository('App\Entities\User')->findAll();
}
return $users;
}
Now lets say that the Criteria is defined like so:
$query = Criteria::create();
$query->where(Criteria::expr()->contains('username', 'ron'));
$query->setMaxResults(10);
And there are actually more than 10 users that match that.
How can I get the total number of the users that match the criteria?
If you set maxResults to 10, you get 10 results ;).
Why don't you call getAll() to get all results and apply the MaxResults later?
//search for Ron's
$query = Criteria::create();
$query->where(Criteria::expr()->contains('username', 'ron'));
//check how many Ron's your database can find
$count = $repo->getAll($query)->count();
//get the first 10 records
$query->setMaxResults(10);
$users = $repo->getAll($query);
I want to limit related records from
$categories = Category::with('exams')->get();
this will get me exams from all categories but what i would like is to get 5 exams from one category and for each category.
Category Model
public function Exams() {
return $this->hasMany('Exam');
}
Exam Model
public function category () {
return $this->belongsTo('Category');
}
I have tried couple of things but couldnt get it to work
First what i found is something like this
$categories = Category::with(['exams' => function($exams){
$exams->limit(5);
}])->get();
But the problem with this is it will only get me 5 records from all categories. Also i have tried to add limit to Category model
public function Exams() {
return $this->hasMany('Exam')->limit(5);
}
But this doesnt do anything and returns as tough it didnt have limit 5.
So is there a way i could do this with Eloquent or should i simply load everything (would like to pass on that) and use break with foreach?
There is no way to do this using Eloquent's eager loading. The options you have are:
Fetch categories with all examps and take only 5 exams for each of them:
$categories = Category::with('exams')->get()->map(function($category) {
$category->exams = $category->exams->take(5);
return $category;
});
It should be ok, as long as you do not have too much exam data in your database - "too much" will vary between projects, just best try and see if it's fast enough for you.
Fetch only categories and then fetch 5 exams for each of them with $category->exams. This will result in more queries being executed - one additional query per fetched category.
I just insert small logic inside it which is working for me.
$categories = Category::with('exams');
Step 1: I count the records which are coming in response
$totalRecordCount = $categories->count()
Step 2: Pass total count inside the with function
$categories->with([
'exams' => function($query) use($totalRecordCount){
$query->take(5*$totalRecordCount);
}
])
Step 3: Now you can retrieve the result as per requirement
$categories->get();
I'm having issues getting a proper count total with my Laravel model.
Model Structure
User
Item
ItemLike
A user can have multiple Items, and each of these Items can have multiple ItemLikes (when a user 'likes' the item).
I can easily get the individual ItemLike counts when using an Item model:
return $this->itemLikes()->count();
But I can't figure out how to get the total # of ItemLike's a User has across all the Item's he owns.
EXAMPLE
User A has 3 Items. Each Item has 5 ItemLike's, for a grand total of 15.
I tried using eager loading on the User model like this:
return $this->items()->with('itemlikes')->get()->count();
But that returns 3 (the # of Items)
These are the queries it ran, which appears like the second query is the one I want, yet every way I try it I still get 3 instead of 15
select * from `items` where `items`.`user_id` = '1000'
select * from `item_likes` where `item_likes`.`item_id` in ('1000', '1001', '1002')
After suggestions from others I found 2 solutions to get the result.
Using whereIn:
$itemViewCount = ItemView::
whereIn('item_views.item_id', $this->items()->lists('id'))
->count();
return $itemViewCount;
2 queries for a total of 410μs
Using join:
$itemViewCount = $this->items()
->join('item_views', 'item_views.item_id', '=', 'items.id')
->count();
return $itemViewCount;
2 queries for a total of 600μs
Isn't it just a case of creating a method that would return the number of items for the model. e.g.:
#UserModel
public function nbLikes()
{
$nbLikes = 0;
foreach($this->items() as $item) {
$nbLikes += $item->itemLikes()->count();
}
return $nbLikes;
}
And then User::nbLikes() should return the piece of data you are looking for?
try this:
$query="select count(il.id) from item_likes il,item itm where il.item_id=itm.id and tm.user_id=1000";
In my CodeIgniter project I'm getting the list of projects and successfully output them on a page. However, the data in one of the columns on that page should be retrieved from a different table in DB using the project ID. Could anybody help me to figure out how that can be done? Basically I need to make another query to that other table specifying the project id but don't actually know how to do that with CodeIgniter.
UPDATE
In the model I'm getting the list of projects with the following function:
function get_projects_list($page, $limit){
$sql = sprintf("SELECT * FROM Project WHERE deleted != 1 LIMIT %d, %d", ($page-1)*$limit, $limit);
$query = $this->db->query($sql);
return $query->result();
}
And in the controller I call the following function:
$projects_list = $this->Project_management_model->get_projects_list($curPage, self::$LIMIT_PER_PAGE);
$data['projects_list'] = $projects_list;
$data['cur_page'] = $curPage;
$data['page_count'] = $pageCount;
$this->load->view('project_management_view', $data);
And in the view I simply run on the $data with foreach and list the results in a table. In that table there's a column where I need to show a result from another table based on the ID of the project of that very row.
Thanks for helping.
You didn't mention whether you are using ActiveRecord or not. I am assuming that you are. I'll also guess that maybe what you need to do is use a JOIN.
If you were using straight SQL, you would do this using some SQL that might look something like this:
SELECT a.appointment_time, u.user_real_name FROM appointment a, site_user u WHERE u.site_user_id = a.user_id;
That would pull the user's name from the user table based on the user id in the appointment table and put it with the appointment time in the query results.
Using ActiveRecord, you would do something like this:
$this->db->select('appointment_time,user_real_name')->from('appointment')->join('site_user', 'site_user_id=appointment_user_id');
But why don't you tell us a little bit more about your question. Specifically, do you want this column in the other table to be related to the rows from the first table? If so, my JOIN suggestion is what you need.
I've actually found a way to do that with a custom helper. Creating a new helper and loading it in the controller gives an option to use the function from that helper in the view.
Thanks.
public function get data()
{
$this->db->flush_cache();
$query = $this->db->get('project_table');
$result = $query->result();
$data = array();
for ($i = 0;$i < count($result);$i++)
{
$data[$i] = $result[$i];
$data[$i]['project_data'] = temp($result[$i]->id);
}
return data;
}
private function temp($id = 0)
{
$this->db->flush_cache();
$this->where('id',$id);
$query = $this->db->get('project_table2');
$result = $query->result();
if (count($result) != 0)
return $result[0]->data;
}
you can do it by some thing like that,or you can use sub-query by query function of database.