Search in query - php

Is there any solutions out there, that make it possible to search in a query.
Example:
I've this simple query:
$this->db->where('start >=',time());
$this->db->where('end <=',strtotime("+1 month"));
$result = $this->db->get('bookings');
What I then want it to be able to make a search that looks like my query above, but which doesn't search in the database, but in the $result results.
So it should be possible to do something like:
$where = array(
'start >=' => time(),
'end <=' => strtotime("+1 day")
);
$get_result_info_by_search = $this->Search_model->get_stored_results($result, $where);
Hope it make sense.
The goal is to reduce the number of calls to the database, because my interval is always the same (I loop through a date range and make the same call for instance 31 times (if 31 days)

This can be done quite easily by looping through the rows and testing 'start' and 'end' values.
/**
* #param CI_DB_result instance $result
* #param array $where with two keys, 'start' and 'end', containing timestamp values, ie.
* $where = ['start' => time(), 'end' => strtotime("+1 month"));
* #return mixed An array of db row objects or NULL if nothing matches
*/
public function get_stored_results($result, $where)
{
$rows = $result->result();
foreach ($rows as $row)
{
if($row->start >= $where['start'] && $row->end <= $where['end'])
{
$matches[] = $row;
}
}
return isset($matches) ? $matches : NULL;
}
If you would rather get back an array of row arrays
public function get_stored_results($result, $where)
{
$rows = $result->result_array();
foreach ($rows as $row)
{
if($row['start'] >= $where['start'] && $row['end'] <= $where['end'])
{
$matches[] = $row;
}
}
return isset($matches) ? $matches : NULL;
}

Might be it will help you
In your controller
$get_result_info_by_search = $this->Search_model->get_stored_results('start','end',$starttime,$endtime);
In your Search Model
function get_stored_results($where1,$where2,$value1,$value2)
`{

Might be it will work for you in your model try to add this code
function get_stored_results($where)
{
foreach($where as $key => $value)
{
$this->db->where($key,$value);
}
$result = $this->db->get('bookings');
}

Related

How to get data from database that result as an array in model codeigniter

I want to make a query that results like this in codeigniter MODEL:
$caldata = array (
15 => 'yes',
17 => 'no'
);
Is that possible to do?
Take NOTE: The 15,17 and yes,no are in the same database table.
There is no core helper function to achieve what you want in CI. But you can create your own helper function:
function pluck($arr = [], $val = '', $key = '')
{
// val - label for value in array
// key - label for key in array
$result = [];
foreach ($arr as $value) {
if(!empty($key)){
$result[$value[$key]] = $value[$val];
}else{
$result[] = $value[$val];
}
}
return $result;
}
you can use result_array() function so you can have something like:
$query = $this->db->select('id,answer')->from('users')->get();
$result = $query->result_array();
print_r($result);
After that you have your array and you can make the $key => $value relation of the fields
After a long search i found an answer. Sample way to do this:
$query = $this->db->select('start_date, class')->from('event')->like('start_date', "$year-$month", 'after')->get();
$datavariable = $query->result();
$caldata = array();
foreach($datavariable as $row){
$caldata[substr($row->start_date,8,2)] = $row->class;
}

Getting multiple fields from database to an array

I wrote an api call in my Symfony project that returns all fields from my entity with the query defined below..
Now, I need to define just three fields like 'id', 'name', 'value' and to pull values from that fields that are currently stored in a database.
public function getChartData() {
$myResults = $this->getMyRepository()
->createQueryBuilder('s')
->groupBy('s.totalCollected')
->orderBy('s.id', 'ASC')
->getQuery()
->getArrayResult();
$result = array("data" => array());
foreach ($myResults as $myResult => $label) {
$result['data'][$schoolResult] = $label["id"];
$result['data'][$schoolResult] = $label["name"];
$result['data'][$schoolResult] = $label["totalCollected"];
}
}
The problem is it return just totalCollected field.
One of errors are Call to a member function getId() on array and so on, and I can't figure out a way to pull data from db...
I cannot see in your code where $schoolResult come from but lets guess it string key of some sort.
Notice you trying to set 3 value on the same key so only the last one remains.
Look at:
$a = array();
$a["key"] = 4;
$a["key"] = 6;
It is simple to see that $a["key"] will contains 6 and not 4 or both.
When you do:
foreach ($myResults as $myResult => $label) {
$result['data'][$schoolResult] = $label["id"];
$result['data'][$schoolResult] = $label["name"];
$result['data'][$schoolResult] = $label["totalCollected"];
}
You override the data in $result['data'][$schoolResult] therefor only try totalCollected is there as the last one to set.
In order to fix that you can use:
foreach ($myResults as $myResult => $label) {
$result['data'][$schoolResult]["id] = $label["id"];
$result['data'][$schoolResult]["name"] = $label["name"];
$result['data'][$schoolResult]["totalCollected"] = $label["totalCollected"];
}
Hope that helps!

PHP MySQL hierarchy data optimization

I have a table employees, which contains columns : employee_id, name, employee_manager_id.
employee_manager_id references to employee_id. It's a hierarchal data.
I have this output using PHP but couldn't achieve it using only one mySQL query. As of now, I need to process the data in PHP using recursive function so i can achieve this kind output.
Sample Array Output
0 => (
employee_id => 2,
name => Jerald,
employee_manager_id => 1,
depth => 1
),
1 => (
employee_id => 3,
name => Mark,
employee_manager_id => 2,
depth => 2
),
2 => (
employee_id => 6,
name => Cyrus,
employee_manager_id => 3,
depth => 3
),
3 => (
employee_id => 4,
name => Gerby,
employee_manager_id => 2,
depth => 2
)
As of now, this is my recursive function in PHP to achieve the output above.
function get_employees_by_hierarchy( $_employee_id = 0, $_depth = 0, $_org_array = array() ) {
if ( $this->org_depth < $_depth ) {
$this->org_depth = $_depth;
}
$_depth++;
$_query = "SELECT * FROM employees WHERE ";
if ( !$_employee_id ) {
$_query .= "employee_manager_id IS NULL OR employee_manager_id = 0";
}
else {
$_query .= "employee_manager_id = " . $this->dbh->quoteSmart( $_employee_id );
}
$_result = $this->query( $_query );
while ( $_row = $_result->fetchRow() ) {
$_row['depth'] = $_depth;
array_push( $_org_array, $_row );
$_org_array = $this->get_employees_by_hierarchy(
$_row['employee_id'],
$_depth,
$_org_array
);
}
return $_org_array;
}
My question is, is there anyway so I can achieve the array output i want using just one mysql query?
If not possible in mysql query, is there anymore to optimize in my current code?
Any help would greatly be appreciated.
Thanks
You can try a nested set a.k.a. celko tree but insert and delete is very expensive. There is also closures and path enumeration (materialized path) but I'm not an expert. MySql doesn't support recursive queries.
I don't think you can get the depth with your current model without doing any processing on the results, but you don't need to make multiple queries.
Assuming $employees is the list of employees indexed by employee_id, you could do something like this:
function set_employee_depth(&$employees, $id) {
if (!isset($employees[$id]['depth'])) {
$employee_manager_id = (int) $employees[$id]['employee_manager_id'];
if (!$employee_manager_id) {
$employees[$id]['depth'] = 0;
} elseif ($employee_manager_id !== $id) {
$employees[$id]['depth'] = 1 + set_employee_depth($employees, $employee_manager_id);
} else {
throw new \Exception('Employee cannot be its own manager!');
}
}
return $employees[$id]['depth'];
}
foreach ($employees as $id => $employee) {
set_employee_depth($employees, $id);
}
So, your table is composed of 3 columns (employee_id, name, employee_manager_id). employee_manager_id is a self reference to employee_id. You want to construct an array with all records, adding an extra field called depth which represents the distance of said employee to the "big boss", with only one query to the database. Is that correct? I'm also assuming that the database structure can't be changed.
If these assumptions are correct, this is a basic HIERARCHICAL/TREE data structure and thus, you have a couple of ways you can tackle this problem.
First Script
The first script runs the results array sequentially, finding the main node / trunk (the big boss) first and then adding it's children, then it's grandchildren and so on. Each time a node is "sorted", it will be removed from the cycle until no nodes are left. It assumes that:
There are no Orphan records (employees with invalid managers_ids)
There are no Circular References, either simple (A is manager of B and B is manager of A) or complex (*A manager of B, B manager of C and C manager of A)
Each path (from the main node to last node) can have an infinite number of nodes
$results are produced by running a simple query SELECT * FROM employees ORDER BY employee_manager_id
Code:
$finalArray = array();
$limit = count($results);
while (count($results) > 0) {
$results[0]['cnt'] = isset($results[0]['cnt']) ? $results[0]['cnt']++ : 0; // set num of times each element was already visited
if ($results[0]['cnt'] === $limit) { //prevent an infinite cycle
break;
}
$manId = $results[0]['manager_id'];
if ($manId === null) {
$results[0]['depth'] = 0;
} else if ( ($key = searchForId($manId, $finalArray)) !== null ) {
$results[0]['depth'] = $finalArray[$key]['depth'] + 1; //use the depth of parent to calculate its own
} else {
$results[] = $results[0]; //parent was not visited yet so we add it to the end of array
array_shift($results);
continue;
}
unset($results[0]['cnt']);
$finalArray[] = array_shift($results);
}
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['id'] === $id) {
return $key;
}
}
return null;
}
This script is pretty straightforward. It only runs one query to the DB. In best case scenario, it will only traverse the array once. In worse case scenario, it will visit each element count(array) - 1, which can be slow with big arrays. However, since the results are pre-sorted, best case scenario will probably be more common.
Second Script
The second script builds an actual tree of elements. It's a bit more complex but achieves similar results. Also, the Depth is calculated dynamically.
class Employee {
public $id;
public $name;
public $manager;
public function __construct($id, $name, Employee $manager = null) {
$this->id = $id;
$this->name = $name;
$this->manager = $manager;
}
public function setManager(Employee $manager) {
$this->manager = $manager;
}
public function getDepth() {
if ($this->manager === null) {
return 0;
} else {
return $this->manager->getDepth() + 1;
}
}
}
$finalArray = array();
$paths = array();
foreach ($results as $r) {
$finalArray[(int) $r['id']] = new Employee((int)$r['id'], $r['name']);
if ($r['manager_id'] !== null) {
$paths[(int) $r['id']] = (int) $r['manager_id'];
}
}
foreach ($paths as $k => $v) {
if (isset($finalArray[$k]) && isset($finalArray[$v])) {
$finalArray[$k]->setManager($finalArray[$v]);
}
}
Here is a link for answer
Here is full code for making tree structure for hierarchy management using php and mysql.

Increment value in array php

I am trying to make a function that grabs all the days that have events that are in a database for a certain user. For instance if there were two events on Jan 23, 2013 it would add Jan 23, 2013 to the array. I got it to work so it adds all the days (without adding the same day twice) but now I want to be able to say how many dates are on each day. So on Jan 23, 2013 it would say they have two events in that day.
I hope this makes sense... I have some code for further aid.
PHP Function (grabbing each day that has events)
//gets upcoming days that have events for a user
public function get_upcoming_days_with_events() {
$return_array = array();
$date_in=null;
$user_id = $this->session->userdata('id');
$query =$this->db->select()->from('events')->where('user_id', $user_id)->get();
foreach ($query->result_array() as $event => $row) {
$date = strtotime($row['date_due']);
if (sizeof($return_array) != 0) {
foreach ($return_array as $date_in_array => $row) {
$d = $row['full_date'];
if (date('Y-m-d', $date) == $d) {
//date is already in array
//increment the number of assignments on this day
$row['number_of_assignments'] += 1;
$date_in = true;
} else{
$date_in = false;
}
}
}
if ($date_in == false) {
$return_array[] = array(
'day' => date('d', $date),
'month' => date('m', $date),
'full_date' => date('Y-m-d', $date),
'number_of_assignments' => 1
);
}
}
return $return_array;
}
So with this I want to be able to increment $return_array['number_of_assignments'] if my function notices that a certain day has more than one event.
Let me know if you need any more info...
Thanks! :)
We can save the info in return_array by index of date, if the date info have not been set into return_array, we make an empty info. Each time, we simply increase number_of_assignments.
public function get_upcoming_days_with_events()
{
$return_array = array();
$user_id = $this->session->userdata('id');
$query =$this->db->select()->from('events')->where('user_id', $user_id)->get();
foreach ($query->result_array() as $event => $row)
{
$date = strtotime($row['date_due']);
$date_key = date('Y-m-d', $date);
if (!isset($return_array[$date_key]))
{
$new_item = array(
'day' => date('d', $date),
'month' => date('m', $date),
'full_date' => $date_key,
'number_of_assignments' => 0,
);
$return_array[$date_key] = $new_item;
}
$return_array[$date_key]['number_of_assignments']++;
}
$return_array = array_values($return_array);
return $return_array;
}
Function: array_count_values() can help you with this, it gives total number of occurance of a value in an array.
For example:
$a = array("apple", "banana", "apple");
var_dump(array_count_values($a));
Will output
array(
[apple] => 2,
[banana] => 1
);
So instead of trying to filter out duplicate events, add them all on the array and then use array_count_values() at last to know their occurenses.

Codeigniter get number of row from search query

I have a query in my controller which searches for the term/keyword that is in the url.
Example /search/keyword
Then through my controller I perform the search doing:
$viewdata['search_results'] =
$this->Search_model->search(strtolower($this->uri->segment(2)),$limit,$offset);
then I check the database from my model like so:
function search($searchquery, $limit, $offset) {
$this->db->from('content');
$this->db->like('title', $searchquery);
$this->db->or_like('content', $searchquery);
$query = $this->db->limit($limit, $offset)->get();
$results = Array();
foreach ($query->result() as $row) {
$results[] = Array(
'title' => '' . strip_tags($row->title) . '',
'link' => base_url() . $row->anchor_url,
'text' => str_ireplace($searchquery, '<b>' . $searchquery . '</b>', strip_tags(neatest_trim($row->content,220,$searchquery,120,120)))
);
}
return $results;
}
}
I would like to know how I can return the number of rows found in my search result to the controller. I will then use the count of rows found for pagination.
How can I get the row count into the controller????
You can add a function in your model that returns the count and call that.
Example:
// model
public function getAffectedRows()
{
return $this->db->affected_rows();
}
...
// controller
$this->Search_model->doQuery();
$numRows = $this->Search_model->getAffectedRows();
You can either just use
$viewdata['search_results'] =
$this->Search_model->search(strtolower($this->uri->segment(2)),$limit,$offset);
$viewdata['search_result_count'] = count( $viewdata['search_results'] );
Or you could return a structured array from your model which includes the count. Something like
return array( 'results' => $result, 'num_results' => $this->db->num_rows() );

Categories