This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 8 years ago.
I need to get the number of rows of a query (so I can paginate results).
As I'm learning codeigniter (and OO php) I wanted to try and chain a ->num_rows() to the query, but it doesn't work:
//this works:
$data['count'] = count($this->events->findEvents($data['date'], $data['keyword']));
//the following doesn't work and generates
// Fatal Error: Call to a member function num_rows() on a non-object
$data['count2'] = $this->events->findEvents($data['date'], $data['keyword'])->num_rows();
the model returns an array of objects, and I think this is the reason why I can't use a method on it.
function findEvents($date, $keyword, $limit = NULL, $offset = NULL)
{
$data = array();
$this->db->select('events.*, venues.*, events.venue AS venue_id');
$this->db->join('venues', 'events.venue = venues.id');
if ($date)
{
$this->db->where('date', $date);
}
if ($keyword)
{
$this->db->like('events.description', $keyword);
$this->db->or_like('venues.description', $keyword);
$this->db->or_like('band', $keyword);
$this->db->or_like('venues.venue', $keyword);
$this->db->or_like('genre', $keyword);
}
$this->db->order_by('date', 'DESC');
$this->db->order_by('events.priority', 'DESC');
$this->db->limit($limit, $offset); //for pagination purposes
$Q = $this->db->get('events');
if ($Q->num_rows() > 0)
{
foreach ($Q->result() as $row)
{
$data[] = $row;
}
}
$Q->free_result();
return $data;
}
Is there anything that i can do to be able to use it? EG, instead of $data[] = $row; I should use another (OO) syntax?
You function findEvents is returning $data which you declared to be an array at the start. This is not an object and does not allow you to access functions using the member access syntax.
To count the number of values in an array see count
Also, from what I understand you not only want the query results returned as an array, but you want to be able to access methods on the result $Q = $this->db->get('events'); However this is not possible as this is a local variable and it is not being returned out. The function here has a result type of array and is not an object and thus has no access to anything, but the array. One solution to this is to return an associative array:
return array("results" => $data, "count" => $Q->num_rows());
Then use array syntax to access the count or the results. Another option is return a new object that has result and count fields and use accessor methods to get to those.
Related
I have a situation here where I want to omit the nested maps and get it done in one liner . Can it be done using chain or any other ways .
self.workorder.tasklist = _.map(self.workorder.tasklists, function (tasklist) {
tasklist.tasklistGroups = _.map(tasklist.tasklistGroups, function (tasklistGroup, tgKey) {
tasklistGroup.tasklistItems = _.map(tasklistGroup.tasklistItems, function (taskListItem, tKey) {
taskListItem = _.omit(taskListItem, ["open"]);
return taskListItem;
});
return tasklistGroup;
});
return tasklist;
});
I don't want so many nested map calls .
Because you are modifying your items in place I would say this is possible:
_.chain(self.workorder.tasklists).map(function(tasklist) {
return tasklist.tasklistGroups;
}).flatten().map(function(group) {
return group.tasklistItems
}).flatten().forEach(function(item) {
delete item.open;
}).value();
Jsfiddle
The idea is to flatten your array to last level (level of items) and then modify them using forEach.
I have calling a function. get table number (result=0) results and updated same table value 0 to 1. i am using update query.i have run this function to return error :: Missing argument 2 for CDbCommand::update().
public function newdisplaycontent()
{
$count = Yii::app()->db->createCommand()
->select()
->from('scrolltable')
->where('result=:result', array(':result'=>0))
->queryAll();
$rs=array();
//print_r($count);
foreach($count as $item){
//process each item here
$rs=$item['ID'];
$user=Yii::app()->db->createCommand()
->update("scrolltable SET result = 1")
->where('ID=:id', array(':id'=>$rs));
}
return $rs;
}
thanks for your feature help..
The correct syntax of update() would be like below:
$user=Yii::app()->db->createCommand()
->update("scrolltable",array("result" => "1"))
->where('ID=:id', array(':id'=>$rs));
As official document:
update() Creates and executes an UPDATE SQL statement. The method will properly escape the column names and bind the values to be updated.
public integer update(string $table, array $columns, mixed $conditions='', array $params=array ( ))
Say I have this method of a RuleFactory:
public function makeFromArray($rules)
{
$array = [];
foreach ($rules as $rule) {
$array[] = new Rule($rule[0], $rule[1]);
}
return $array;
}
I want to test that the return array contains Rule elements. Here is my test:
function it_should_create_multiple_rules_at_once()
{
$rules = [
['required', 'Please provide your first name'],
['alpha', 'Please provide a valid first name']
];
$this->makeFromArray($rules)->shouldHaveCount(2);
$this->makeFromArray($rules)[0]->shouldBeInstanceOf('Rule');
$this->makeFromArray($rules)[1]->shouldBeInstanceOf('Rule');
}
But this does not work, it throws an error in PHPSpec.
The strange thing is that I can do this just fine on other methods that return arrays, but for some reason I cannot do that here.
The error I get is this:
! it should create multiple rules at once
method [array:2] not found
How do I test the contents of this return array, WITHOUT creating my own inline matcher?
Your method accepts a single rule, not all of them. The spec should be:
$this->makeFromArray($rules)->shouldHaveCount(2);
$this->makeFromArray($rules[0])[0]->shouldBeAnInstanceOf('Rule');
$this->makeFromArray($rules[1])[1]->shouldBeAnInstanceOf('Rule');
Or, to avoid multiple calls:
$rules = $this->makeFromArray($rules);
$rules->shouldHaveCount(2);
$rules[0]->shouldBeAnInstanceOf('Rule');
$rules[1]->shouldBeAnInstanceOf('Rule');
Still, the most readable version would be the one leveraging a custom matcher:
$rules->shouldHaveCount(2);
$rules->shouldContainOnlyInstancesOf('Rule');
I'm trying to implement for loop to update time.
$files = File::model()->findAll('type="A" AND id='.$id);
function files($files,$limit=null){
$limit = isset($limit) ? $limit : count($files);
for($i=0;$i<=$limit;$i++){
$files[$i]->date = date('Y:m:d H:i:s');
$files[$i]->update();
}
}
This function return error undefined offset 1.
What is the result of findAll method? Is it a multidimensional array of records? And How could I fixed this error?
You are setting $limit to count($files) but using $i<=$limit in your loop. Should be < instead.
for($i=0; $i<$limit; $i++){
Since there is a chance of an external $limit being applied you could use a foreach loop with a conditional break.
foreach($files as $a => $file) {
if($a == $limit) {
break;
}
$file->date = date('Y:m:d H:i:s');
$file->update();
}
Note that findAll() without a limit retrieves all the records from the databases for that table. Perhaps you should consider adding the limit through CDbCriteria
function mysql_insert($data_array){
$sql = "insert into `". $this->table_name. '`';
$array_keys = array_keys($data_array);
$array_keys_comma = implode(",\n", preg_replace('/^(.*?)$/', "`$1`", $array_keys));
for($a=0,$b=count($data_array); $a<$b; $a++){ $question_marks .="?,"; }
$array_values = array_values($data_array);
$array_values_comma = implode(",", $array_values);
$sql.= " ($array_keys_comma) ";
$sql.= " values(". substr($question_marks, 0,-1) .")";
$prepare = $this->connDB->prepare($sql);
$insert = $prepare->execute(array($array_values_comma));
}
I want to creat like this universal functions, $data_array-comes from $_POST
This function will work for all form. But i dont know what is my wrong :S
I don't know what is my wrong
That's quite easy to know: number of bound variables does not match number of tokens.
I want to creat like this universal functions, $data_array-comes from $_POST
Here you go: Insert/update helper function using PDO
$array_values_comma is a scalar after you implode() the array. So you always pass an array of one element to your execute() function. You should pass $array_values.
Here's how I'd write this function:
function mysql_insert($data_array){
$columns = array_keys($data_array);
$column_list_delimited = implode(",",
array_map(function ($name) { return "`$name`"; }, $columns));
$question_marks = implode(",", array_fill(1, count($data_array), "?"));
$sql = "insert into `{$this->table_name}` ($column_list_delimited)
values ($question_marks)";
// always check for these functions returning FALSE, which indicates an error
// or alternatively set the PDO attribute to use exceptions
$prepare = $this->connDB->prepare($sql);
if ($prepare === false) {
trigger_error(print_r($this->connDB->errorInfo(),true), E_USER_ERROR);
}
$insert = $prepare->execute(array_values($data_array));
if ($insert === false) {
trigger_error(print_r($prepare->errorInfo(),true), E_USER_ERROR);
}
}
A further improvement would be to do some validation of $this->table_name and the keys of $data_array so you know they match an existing table and its columns.
See my answer to escaping column name with PDO for an example of validating column names.