Codeigniter search term with pagination - codeigniter

Still getting to grips with PHP and Codeigniter and I'm having an issue with passing a search term parameter from my Controller to my Model, with pagination.
I have a fully functioning script (with pagination) working already... However, trying to include the input post search term to the model is messing it all up (or I'm messing it all up).
Working script - Controller:
public function search()
{
$this->load->model('Products_model');
$config['base_url'] = base_url() . '/products/search/';
$config['total_rows'] = $this->db->count_all('affiliate_window');
$config['per_page'] = 25;
$config['uri_segment'] = 3;
$this->pagination->initialize($config);
$data['offset_no'] = $this->uri->segment(3);
$data['items'] = $this->Products_model->get_search($config['per_page'], $data['offset_no']);
$this->load->view('header_view');
$this->load->view('products_view', $data);
$this->load->view('footer_view');
}
Working script - Model:
function get_search($limit, $offset)
{
$query = $this->db->get('mydb', $limit, $offset);
return $query->result();
}
So, any advice on how do I now go about passing $this->input->post('search_term'); from Controller to my model to use like this:
function get_search($limit, $offset)
{
$this->db->like('name', '$SEARCHTERM');
$query = $this->db->get('mydb', $limit, $offset);
return $query->result();
}
Furthermore, I believe I'm next going to run into an issue with keeping the search term variable throughout each page.
Any advice very welcome - I've been working on this for hours with no results! :)

So, understand that your pagination code & all the other code are "unrelated" - meaning, they don't require the other one to function.
You will pass your search term in to your model function like any other parameter & search on it in the query; limit & offset are simply tagged to the end of your query as you are doing now.
So if searching for "myterm", you'll just build a query with:
WHERE term = "myterm" LIMIT offset, limit
It's really quite simple once you get your head around what you are actually doing

Related

How I can paginate DB::select(...) result and get links() method?

I have a big and difficult SQL query. It works fine for me. And I have the following code in the controller:
public function index(OpenRegDepDataReportInterface $openRegDepDataReport, Request $request): Renderable
{
$applications = $openRegDepDataReport->getReport($advertisers, $category);
return view('applications.index', compact('applications'));
}
So, the method getReport gives me a result of DB::select('<here is my big diffecult SQL>'), and, as well known it's an array.
But as you can see I'm trying to pass the result on a view. And, of course, I would like to call $applications->links() in the view, like for eloquent collection. Which is proper and faster way to do that?
doc
To display pagination at the table, you must call the select and then the pagination method.
in Controller:
$test = DB::table('users')->select('id')->paginate(10);
in View:
$test->links();
So based on the documentation if your $applications returns a Query Builder result, then just append ->paginate(10); to it.
https://laravel.com/docs/master/pagination#paginating-query-builder-results
$applications = $openRegDepDataReport->getReport($advertisers, $category)->paginate(10);
Simple answer, use paginate() method:
$basicQuery = DB::select(DB::raw("<here is the big diffcult SQL query>"));
However, paginate() works only on collections, and since you have an array of objects, you need to turn it into a collection first, using the forPage() method:
The forPage method returns a new collection containing the items that would be present on a given page number. The method accepts the page number as its first argument and the number of items to show per page as its second argument:
$collection = collect($basicQuery);
$chunk = $collection->forPage(2, 3);
$chunk->all();
Complicated answer: build a paginator instance yourself:
$perPage = 10;
$page = $request->input("page", 1);
$skip = $page * $perPage;
if($take < 1) { $take = 1; }
if($skip < 0) { $skip = 0; }
$basicQuery = DB::select(DB::raw("<here is the big diffcult SQL query>"));
$totalCount = $basicQuery->count();
$results = $basicQuery
->take($perPage)
->skip($skip)
->get();
$paginator = new \Illuminate\Pagination\LengthAwarePaginator($results, $totalCount, $take, $page);
return $paginator;
I would recommend using the paginate() method.
You can read more about Laravel's pagination.

Where to write search logic in laravel

I am writing a search script and want to return results based on the user's query.
Following is my route :-
Route::get('/search/{city}/{searchquery}', 'SearchController#search');
Controller
public function search($city, $query){
strtolower($query);
$commonWords = array('a','able','about','above','abroad'.....);
$cleanQuery = preg_replace('/\b('.implode('|',$commonWords).')\b/','',$query);
$cleanQuery = $s = preg_replace('/[^a-z0-9]+/i', ' ', $cleanQuery);
$queryarray = explode(' ',$cleanQuery);
$queryarray = array_filter( $queryarray );
$queryarray = array_slice( $queryarray, 0 );
//code to match each query word with MySQL fields such as title, description
return $result;
}
I believe, all this logic and code should not be written in the controller. What can I use to write logic and use controller to only return result
The simplest way would be to use models for that. Just write a method that gets keywords and parses it into sql query. You could use scope methods to allow for more flexibility.
public function scopeSearch($q, $keywords)
{
// ... $keywords processing here
$keywordsArray = explode(',', $keywords);
return $query->whereIn('keyword', $keywordsArray);
// OR maybe something like this?
return $query->where('keywords', 'LIKE', '%'. $keywords .'%');
}
You could use this method in a controller like that:
$city = new City();
$results = $city->search($keywords)->where(/* additional conditions could be added here */)->get();
Even if you decide not to use scope methods, I would still advise to return query builder objects instead of collections as to allow for better flexibility, such as implementing pagination or additional manipulation in controllers where needed.
You could also use Repositories if you are not afraid to add more complexify to gain more flexibility. More on that here: https://laracasts.com/lessons/repositories-simplified

CI pagination syntax for getting results

Assume that the config is done and it is intialized, then time for the results to be paginated.
On this line of code.
$data['records'] = $this->db->get('tablename', $config['per_page'], $this->uri->segment(3));
Is there anyway of changing the above line of code. Since I have 3 tables with ERD relationship. So in my 3rd table consists lots of rows that are connected to the other 2 tables. I want to make a model function where i will manually query the results. How am i supposed to write it?
$data['records'] = $this->load->model('manual_querying'), $config['per_page'], $this->uri->segment(3);
Im not sure if its correct, i am still unable to test it if its correct since im not done with my pagination yet.
In model, write a function
public function get_records($per_page,$page)
{
$this->db->select("*");
$this->db->from("table1 as t1");
$this->db->join("table2 as t2","t1.id = t2.t1_id");
$this->db->join("table3 as t3","t1.id = t3.t1_id");
$this->db->limit($per_page,$page);
$res = $this->db->get();
return $res;
}
In controller,
$this->load->model('your_model');
$data['records'] = $this->your_model->get_records($config['per_page'], $this->uri->segment(3));

Codeigniter: does $this->db->last_query(); execute a query?

Does query execution happen at the get_where() clause of the following codeigniter active record statement?
$this->db->select('*');
$q = $this->db->get_where('Contacts', array('id' => $contact_id));
$sql = $this->db->last_query();
Or does it happens once you call the result_array()?
And is $this->db->last_query(); a reliable way in getting the query string.
The query execution happens on all get methods like
$this->db->get('table_name');
$this->db->get_where('table_name',$array);
While last_query contains the last query which was run
$this->db->last_query();
If you want to get query string without execution you will have to do this.
Go to system/database/DB_active_rec.php Remove public or protected keyword from these functions
public function _compile_select($select_override = FALSE)
public function _reset_select()
Now you can write query and get it in a variable
$this->db->select('trans_id');
$this->db->from('myTable');
$this->db->where('code','B');
$subQuery = $this->db->_compile_select();
Now reset query so if you want to write another query the object will be cleared.
$this->db->_reset_select();
And the thing is done. Cheers!!!
Note : While using this way you must use
$this->db->from('myTable')
instead of
$this->db->get('myTable')
which runs the query.
Take a look at this example
For me save_queries option was turned off so,
$this->db->save_queries = TRUE; //Turn ON save_queries for temporary use.
$str = $this->db->last_query();
echo $str;
Ref: Can't get result from $this->db->last_query(); codeigniter
For Me It Works Perfectly: Source Disclosure : This Source website Belongs to me , i am also sharing solutions on my website ...
public function index()
{
$db = \Config\Database::connect();
$heroesCount = $db->table('products')->countAll();
echo $db->getLastQuery();
exit;
}

laravel 4 paginate collection

I cant create a proper pagination system using laravel 4. I have the following models and function that return collections:
Model Restaurant:
public function fooditem()
{
return $this->hasMany('Fooditem','rest_id');
}
public function get_rest_foods($id){
return Restaurant::find($id)->fooditem->toArray();
}
The second function returns all food items for a certain restaurant as an array. I also use this in an API call.
in my controller i have this:
$food = $food->get_rest_foods($id);
$paginator = Paginator::make($food, 10, 5);
I pass the paginator to the view and it shows the links ok but also shows all my item from the food array.
I tried using
public function get_rest_foods($id){
return Restaurant::find($id)->fooditem->paginate(5);
}
but i get an error:
FatalErrorException: Error: Call to undefined method Illuminate\Database\Eloquent\Collection::paginate()
I searched this and many other sites but cant understant how to paginate a collection.
Thanks for your help
The paginator must get the items that it would normally get from a database query with an offset/limit statement.
So when you have a collection with all items, you should do the offset/limit yourself.
$food = $food->get_rest_foods($id);
$page = 1;
if( !empty(Input::get['page']) ) {
$page = Input::get['page'];
}
$perPage = 15;
$offset = (($page - 1) * $perPage);
$food = Paginator::make($food->slice($offset,$perPage, true)->all(), $food->count(), $perPage);
I created a subclass of Collection and implemented my own paginate method
public function paginate($perPage) {
$pagination = App::make('paginator');
$count = $this->count();
$page = $pagination->getCurrentPage($count);
$items = $this->slice(($page - 1) * $perPage, $perPage)->all();
$pagination = $pagination->make($items, $count, $perPage);
return $pagination;
}
The Laravel paginator does not do any of the splicing for you. Typically the paginator should be used hand in hand with Eloquent/Fluent. In your second example you should be doing it like this.
return Restaurant::find($id)->fooditem()->paginate(5);
Without calling the actual method you'll just be getting a collection of results and not the query builder instance.
If you want to use the paginator manually you need to pass in the spliced array (the correct items for the current page). This usually involves determining the current page, the total results and total pages. That's why, where possibly, it's best to use it with Eloquent or Fluent.

Resources