Codeigniter alter query - php

I'm building a search function and i'm pretty sure the proper way is to only get the # of results you want to display, in my case 20 per page. I'm wondering what is the best way for me to change that select('*') statement to return the total # of results select('count(*)'); and rerun the exact same query?
$this->db->select('*');
$this->db->from('MyTable');
$this->db->where('some complex conditions');
$this->db->join('a bunch of joins);
$this->db->limit('20','$page*20');
to
$this->db->select('count(*)');
/* reuse this part */
$this->db->from('MyTable');
$this->db->where('some complex conditions');
$this->db->join('a bunch of joins);
/* reuse this part */
run first query
$q1 = $this->db->get()->result_array();
run second query
$q2 = $this->db->get('q1 with different select')->result_array();
array_merge($q1,$q2);

Codeigniter actually has a pagination helper that is pretty useful:
https://ellislab.com/codeIgniter/user-guide/libraries/pagination.html
If you don't prefer to use it, you can pass in the current query number that you are at to the controller through the url.For example www.example.com/page/search/40. Where the query will then take that number to use for the limit.

You Can also do this way
// For required output
$this->db->select('');
$this->db->from();
$this->db->join();
$this->db->order_by();
$this->db->limit((int)$page['limit'],(int)$page['start']);
$list['list'] = $result->result();
// To count total number of rows
$this->db->select('');
$this->db->from();
$this->db->join();
$this->db->order_by();
$result_total = $this->db->get();
$list['list'] = $result->result();
$list['total'] = $result_total->num_rows();
return $list;
}

Related

Ignore "where" clause in Laravel database query if no filter is provided

I'm currently trying to find the cleanest way to go about a query in Laravel 5.1. I'm creating an API that will return a JSON string from a MySQL database.
I would like to be able to have a URL like
mydomain.com/api/courses
which will return a JSON list of all of our courses. And I would also like to be able to pass in a GET query parameter like
mydomain.com/api/courses?subject=BUS
which will return only business courses. Pretty basic so far. In my controller, I have
$subject = \Request::input('subject');
if ($subject) { //filter to only query parameters
$results = \DB::table('course_listings')
->where('subject', $subject)
->get();
} else { //return all results
$results = \DB::table('course_listings')->get();
}
However, it seems a little unnecessarily messy, especially if I want to start adding in additional query parameters. What I would like to do is to be able to just ignore the where() if the query parameter is blank.
$results = \DB::table('course_listings')
->where('subject', $subject) //ignore this line if no $subject
->get();
And for performance purposes, I would also want to avoid having to load all of the results, and then applying the filter afterwards. Is there anything in Laravel built for this?
You can save your query to a variable, and then only apply the where in your if block:
$subject = Request::input('subject');
$query = DB::table('course_listings');
if ($subject) {
$query->where('subject', $subject);
}
$results = $query->get();
If you want to completely forgo the if statement, you can do this:
$constraints = array_only(Request::input(), 'subject');
$results = DB::table('course_listings')->where($constraints)->get();

Can we merge doctrine querybuilders and retrieve each ones' results ? is that a best practice?

I have a website where I populate the first page with objects of different nature (last posts, last recipes, last ingredients published). I have currently one querybuilder and then one query for each of them because I call ->getQuery()->getResult() on each of them.
Is there not a way to merge all those querybuilders before executing the query so as to retrieve an array of results made of the results of each of those querybuilders ?
Would that be a best practice ? How would we do it ?
EDIT: what I hoped we could do:
$recipesQueryBuilder = $this->getDoctrine->getRepository('Recipe')->createQueryBuilder('r');
$postsQueryBuilder = $this->getDoctrine->getRepository('Post')->createQueryBuilder('p');
$results = mergeQueryBuilder($recipesQueryBuilder, $postQueryBuilder)->getQuery()->getResult();
$recipes = $results['r'];
$posts = $results['p'];
I do this with many of our queries. I doubt there is a formal "best practice" for this kind of thing, however I can vouch for the fact that re-using builders does simplify the code. For example:
public function getListBuilder(User $user)
{
return $this->createQueryBuilder('l')->where('l.user = :user')->setParameter('user', $user)->orderBy('l.name');
}
I have a number of queries that re-use this base builder. For example:
public function countLists(User $user = null)
{
$qb = $this->getListBuilder($user);
return $qb->select('COUNT(l)')->getQuery()->getSingleScalarResult();
}
Likewise another method findActiveLists() changes the order to createdAt and generates a query with setMaxResults() specified.

Convert the result Set into Database Object in codeigniter

I am trying to write a CSV in Codeignter for a result set fetched from db.
I am already using the solution mentioned here. Reports in Codeigniter
But the issue is that it writes the whole table. Now I want to fetch and write specific records. So here is my model code.
$where = "hangtag_spoc_number = 2202";
$result = $this->db->select('*')
->from('hangtag_request')
->where($where)
->get()
->result_array();
return $result;
It gives me this error.
You must submit a valid result object
If I change the model code to this
return $query = $this->db->get('hangtag_request');
It works perfectly. Is there any way I can make my model code to return the results in the form of DB object? Coz it seems thats the form we need.
Thanks.
If you need result object then you shouldn't use the result_array()
$this->db->get();
The above statement runs the selection query and returns the result.It does return in form that can be used for presentation.
result_array()
This function returns the query result as an array, or an empty array when no result is produced.
Its good to use return $query = $this->db->get('hangtag_request'); for obtaining result object.
I got it solved.
Just had to remove result_array() so the correct code becomes
$where = "hangtag_spoc_number = 2202";
$result = $this->db->select('*')
->from('hangtag_request')
->where($where)
->get();
return $result;

problem with empty values in a database

I have a function which I use all over the place to pull users friends out of a database. However I recently had to delete a few users for causing problems on the forums, this has given me a few "Trying to get property of non-object" problems and I have traced it down to this function.
function isFriend($user_id, $friend_id){
$this->db->from('friends');
$this->db->where('user_id', $user_id);
$this->db->where('friend_id', $friend_id);
$this->db->where('removed', 0);
$query = $this->db->get();
$result = $query->result();
return count($result);
}
Does anyone know how I can adjust this function to ignore deleted users?
If all you're doing is counting the results you can try this instead:
$this->db->count_all_results();
Like this:
function isFriend($user_id, $friend_id)
{
$num = $this->db
->from('friends')
->where('user_id', $user_id)
->where('friend_id', $friend_id)
->where('removed', 0)
->from('TABLE_NAME')
->count_all_results();
return $num;
}
It should return 0 if there are no results, whereas $query in your current function (I believe) may not return an object you can call result() on (hence your error).
http://codeigniter.com/user_guide/database/active_record.html
$this->db->count_all_results();
Permits you to determine the number of rows in a particular Active
Record query. Queries will accept Active Record restrictors such as
where(), or_where(), like(), or_like(), etc. Example:
echo $this->db->count_all_results('my_table'); // Produces an integer, like 25
$this->db->like('title', 'match');
$this->db->from('my_table'); echo
$this->db->count_all_results(); // Produces an integer, like 17
There may be "better" ways, but without knowing the guts of your application it's hard to say.
why did you actualy remove them from database when you have the flag "removed" ?
Anyway, i think you should also remove the connections of those removed users, i don't see anything wrong with the function.
Trying to alter the function to work, it's just a hack and it's not good practice.
I think the function itself looks fine but it seem likely your errors are caused when the query returns 0 results.
if the removed col in the friends table or the users table?
Maybe you should perform a join to the users table.

Codeigniter - Active record - sql - complex join

I have a function that retrieves all tags from a table:
function global_popular_tags() {
$this->db->select('tags.*, COUNT(tags.id) AS count');
$this->db->from('tags');
$this->db->join('tags_to_work', 'tags.id = tags_to_work.tag_id');
$this->db->group_by('tags.id');
$this->db->order_by('count', 'desc');
$query = $this->db->get()->result_array();
return $query;
}
I have another table called 'work'. The 'work' table has a 'draft' column with values of either 1 or 0. I want the COUNT(tags.id) to take into account whether the work with the specific tag is in draft mode (1) or not.
Say there are 10 pieces of work tagged with, for example, 'design'. The COUNT will be 10. But 2 of these pieces of work are in draft mode, so the COUNT should really be 8. How do I manage this?
Try changing:
$this->db->from('tags');
$this->db->join('tags_to_work', 'tags.id = tags_to_work.tag_id');
To:
$this->db->from('tags, work');
$this->db->join('tags_to_work', 'tags.id=tags_to_work.tag_id AND work.id=tags_to_work.work_id');
And Adding:
$this->db->where('work.drafts', 0);
You can use pure sql instead of using the active record class, I myself are working with CI for over 2 years and most of the time I am avoiding the active record class, cause straight sql is much easier to debug and write complex queries.
This is how i would use it.
$sql = "SELECT...your sql here";
$q = $this->db->query($sql);
...
//Do something with your query here

Categories