I have following two classes called One and Two respectively. Class One has database stuff in it. Where method connect() returns a variable (a property) that is the database handler ($dbh). I have used connect() literally hundreds of times and it works as anticipated. Here too, (in method query()) it should work correctly. Now the work the method query() has to do is to prepare a statement ($query in this case) and execute it, after which it fetches data as an associative array and returns the data. I call this method in multiple methods, and works fine in all except in the method some_method() in class Two.
class One {
protected function query($sql, $params=[]){
$query = $this->connect()->prepare($sql); // Method connect() returns database handler ($dbh)
$query->execute($params);
$storage = $query->fetch(); // Fetch as an associative array
return $storage;
}
}
Now here in some_method() in class Two, method query()(from class One), is called where a variable $sql and also an associative array $params are declared as shown in the code below. All this method has to do is to call the method query(), with the parameters $sql and $params, and store the result in $storage. If $storage==false, return false and if $storage has some value other than false, return true. And this result (i.e., true or false) depends on if the database has an entry in the column class_date as specified in $params['date']. Now here comes the problem, irrespective of if the database has that value in that column, the method some_method(), always returns false. I don't know what mistake I'm doing here. Can someone point it out please.
class Two extends class One{
public function some_method($date){
$sql = 'SELECT class_date FROM table_name WHERE id=:id AND class_date=:date';
$params = [
'id' => $this->user_id,
'date' => $date
];
$array = $this->query($sql, $params);
return ($array==false) ? false : true;
}
}
Related
I am trying to write test cod for function in repository.My repo code is;
public function getcomment($id){
$data = ProductComment::active()
->where('productId',$id)
->orderBy('date','desc')
->simplePaginate(5)->items();
return $data;
}
for this I wrote this test code;
public function testgetcomment(){
/*$Mock = \Mockery::mock(Product::class);
$Mock->shouldReceive('getId')
->once()
->andReturn(true);
$this->repo->getcomment($Mock->getId());
$this->assertTrue(true);*/
$ecpected=ProductComment::where('productId',1)->get();
$actual=$this->repo->getcomment(1);
self::assertEquals($expected,$actual);}
I am getting this error;
Array () does not match expected type "object". Can you help me?
The items() function on a pagination object returns an array of objects. However, the get() function on Eloquent queries returns a collection of objects.
To fix your test, return the underlying array from the collection.
$ecpected = ProductComment::where('productId',1)->get()->toArray();
$actual = $this->repo->getcomment(1);
self::assertEquals($expected,$actual);
1.Check your variables names ($ecpected contains data you are pulling from Model, and $expected is the one you are trying to compare).
$ecpected=ProductComment::where('productId',1)->get();
$actual=$this->repo->getcomment(1);
self::assertEquals($expected,$actual);
2.You can check dumps for both variables in comparison (to be sure that you are getting different type (Your repo returns an Array, while querying ProductComment returning you an Object/collection.).
dump($expected);
dump($actual);
3. You probably need to use toArray() method on your $expected variable to achieve your goal.
I am new in PHP as well as in Codeigniter.
public function test_table()
{
$q = $this->db
->where('id',$id)
->get('table_name');
return $q->row();
}
// test_table() is a function written to models in codeigniter .
Can anyone please share me in details Why we are used return statement to insert or retrieve data in database ?
From the php manual:
If called from within a function, the return statement immediately ends execution of the current function, and returns its argument as the value of the function call
http://php.net/manual/en/function.return.php
That means the "return" statement will return the data to the parent method who called it.
The behavior of DB operations will depend on the frameworks/libraries you are using.
From the codeigniter manual:
insert([$table = ''[, $set = NULL[, $escape = NULL]]])
RETURNS: TRUE on success, FALSE on failure
https://www.codeigniter.com/userguide3/database/query_builder.html
When selecting, the "return" statement will return the row from the database or "false" if not found.
First I have to say that I tried to find solution, and i didn't.
Basic question:
$Br = new BrandTop;
dd( $Br->limit(10)->get() ); // Will return 10 rows
and
$Br = new BrandTop;
$Br->limit(10);
dd( $Br->get() ); // Will return all rows.
So, the basic question - why? How can I set some limit for Model, but still work with it, for example set (or not set) some where or order depends on other variables.
Advanced question:
I want to use Model like this:
class BrandTop extends Model
{
public function withBrand() {
return $this->leftJoin('brand', 'brand.id' , '=', 'brandtop.brand_id');
}
public function forType($type) // there is much more conditions for type
{
return $this->where(['type' => $type]);
}
// main function
public function forSunglasses($limit = 0, $logo = false)
{
if ($logo)
$this->where(['menu_logo' => 1])->orderBy('total_sales', 'desc');
if ($limit)
$this->limit($limit);
return $this->forType('sunglasses')->withBrand();
// But there goes Error, because forType() return Builder object, and it has no withBrand() method
}
}
So, there is much more conditions, and it's much easier to set all conditions in separate methods. But how?
Model vs Builder
The thing to understand here is the difference between the Model object and the underlying Builder (query builder) object.
The statement $Br = new BrandTop; will create a new instance of a Model, and assign it to the $Br variable. Next, the $Br->limit(10) statement will create a new instance of a Builder object for the brand_tops table, with a limit of 10 applied.
In your first example, by doing $Br->limit(10)->get(), you're calling get() on the Builder that has your limit applied.
In your second example, your individual $Br->limit(10) creates the new Builder instance, but never uses it for anything. The next statement, $Br->get(), creates another new Builder instance without any constraints, so it retrieves all the records.
To be able to build up your query, you need to assign your Builder instance to a variable, and continue to modify that instance before finally calling get(). For example, to get your second example to work:
$query = BrandTop::query();
$query->limit(10);
$query->where(/*conditions*/);
dd($query->get());
Query Scopes
In relation to the second part of your question, you probably want to look into query scopes.
class BrandTop extends Model
{
// renamed to "JoinBrand" instead of "WithBrand", as "with" would imply
// an eager loaded relationship vs a joined table
public function scopeJoinBrand($query)
{
return $query->leftJoin('brand', 'brand.id' , '=', 'brandtop.brand_id');
}
// got rid of "for" prefix
public function scopeType($query, $type)
{
return $query->where('type', $type);
}
// got rid of "for" prefix
public function scopeSunglasses($query, $limit = 0, $logo = false)
{
if ($logo)
$query->where(['menu_logo' => 1])->orderBy('total_sales', 'desc');
if ($limit)
$query->limit($limit);
return $query->type('sunglasses')->joinBrand();
}
}
With the above model, your code would look something like:
dd(BrandTop::sunglasses()->get());
// or, more verbosely:
$query = BrandTop::query();
$query->sunglasses(); // $query already an object, no need to reassign it to itself
dd($query->get());
i use classes for some typical MySQL queries, like getting specific users, news etc. And afterwards I call function query(), which calls mysqli class and query and returns the query like this:
class Users {
[...]
public function query() {
$mysql = new mysqli([...]);
$mysql->query($this->query);
return $mysql;
}
}
When I use it for ex. in $variable like:
$variable = new Users();
$variable->setNew($params)->query();
I have still stored object of Users in $variable. Is there any way to automatically 'update' the variable to be object of mysqli_result (in this case or different class in simillar situation) without using $variable = $variable->setNew($params)->query();?
Thank you for your advice.
You can do this in a one liner:
$variable = (new Users())->setNew($params)->query();
$variable now contains the return of query()
I am trying to access a functions variable from another function in the same class. i am fairly new to the concept and I can get it to work in another function but when I try to create it's own function I get an Trying to get property of non-object I know what that means but it's confusing as to what needs to be returned in my function since it does work in my other function.
Function getting the error
public function getEditTotal($id) {
$techs = $this->technician();
$tech = $techs->tech;
var_dump($tech); die;
return View::make('report.edit', array('pageTitle' => 'Edit Report Total', 'id' => $id, 'tech' => $tech));
}`
The function I am trying to call
public function technician() {
$tech = DB::table('technician')
->get();
return $tech;
}
I had that same $tech variable in this function and it worked perfectly fine if I called $this->setComplete($id) instead.
Returned statement in the setComplete($id) function
return View::make('report.total', array('pageTitle' => 'Reporting', 'id' => $id, 'tech' => $tech, 'status' => $status));
I am sure it's just the way it's being returned since that variable is being returned in setComplete($id) in the array. I just don't know how to strictly call it in the technician() function.
When you call $techs = $this->technician(); you are setting the $techs to be whatever the value of the $tech variable in the technician function. That is going to be the result of DB::table('technician')
->get();
Theoretically this should be an array of objects where each object represents one row in the technician table.
If you want to know what's going on, add a var_dump($tech) inside the your technician() function, just prior to the return $tech statement.
Since you indicate it is working as expected, you're getting an array of objects. I'm not sure what you want to do with those, but inside the controller:
foreach ($techs as $tech) {
echo $tech->somefieldInTech;
}
or perhaps
echo $techs[0]->somefieldInTech;
So to be clear, in your laravel template, you might want to pass the entire $techs and foreach through it in the template, although from your code it's not clear what you need to do with the data.