Kohana convert database object to int - php

i have two values. one represents a number of objects
$a = $product->count_all();
and the other represents a value from the database:
$first = Model::factory('product')->sale($sale_id)->find();
i need the sum between the two. the second returns the first id that satsfies the query conditions. how can i convert the $first variable to int in kohana or how can i make this sum?? thank you!

Use $_ignored_columns for it:
protected $_ignored_columns = array('count');
So, you can initialize it
($first->count = $a;) and get as a
model column ($count =
$first->count;).
Create special method get_count() in your
model:
protected $_row_count;
public function get_count()
{
if ( $this->_row_count === NULL)
{
$this->_row_count = ORM::factory($this->_object_name)->count_all();
}
return $this->_row_count;
}

Related

How to map GROUP_CONCAT with pdo->fetchAll and mode PDO::FETCH_CLASS from string to an array

I was wondering how fetchAll of PDO is actually implemented to get an Idea how to map the result from the database including a GROUP_CONCAT() comma separated list string to an array property.
Having a sql like
$query = "Select a.id, GROUP_CONCAT(b.name) AS referencingNames FROM a JOIN b on (a.id = b.id_a)"
Will return something like
id (int)
referencingNames (srting)
1
Mark, Mona, Sam
2
Jim, Tom, Sara, Mike
3
...
My Object to map to looks like this
class someObject {
public int $id;
public array $referencingNames;
}
When I call my php code then:
$pdo = new PDO(....)
$statement = $pdo->prepare($query);
$statement->execute();
$objects = $statement->fetchAll(PDO::FETCH_CLASS, someObject::class);
I am running into a type error, as referencingNames is obviously a string.
What I then tried was to set $referencingNames private and use the magic function __set() as it says in the php docs the following
is run when writing data to inaccessible (protected or private) or non-existing properties
class someObject {
public int $id;
private string $referencingNames;
public ?array $refNamesList;
public function __set($name, $value)
{
if($name == "referencingNames") {
$this->referencingNames = $value;
$this->refNamesList = explode(",", $value);
} else {
$this->$name = $value;
}
}
}
The bad news: this didn't work out. I get back an object where refNamesList stays null. Logging the call of __set() did not give me any output, so I assume, it does not get called.
Has anybody an Idea how I can map GROUP_CONCAT to an array with PDOs fetchAll() without building my own solution?
I mean, fetching all, and iterating the whole thing is still an option, but I was wondering if I can do this more elegantly anyhow.
As the name of the column you are loading is part of the class, it's setting that value anyway without having to call the __set method. So one way (seems to work) is to add a column alias which doesn't exist in the class - nameList in this example...
$query = "Select a.id, GROUP_CONCAT(b.name) AS nameList
FROM a
JOIN b on (a.id = b.id_a)"
this should then call the __set method and you can process when you get nameList...
class someObject {
public int $id;
public array $referencingNames;
public function __set($name, $value)
{
if($name == "nameList") {
$this->referencingNames = explode(",", $value);
} else {
$this->$name = $value;
}
}
}

How to add a new key in result of codeigniter model return result()

I have a function in my model that get all company details I am fetch this
I have to add a new key city_name in my return result() how can I add ?? I am very confused but I am not get any useable example.
function xxxx($search=array(),$page,$limit){
$this->db->select("*");
$this->db->from("xxx");
$this->db->join("xx","xx.xx=xxx.xx");
$this->db->limit($limit,$page);
$company_data = $this->db->get();
if($company_data->num_rows()){
return $company_data->result();
}
else{
return 0;
}
}
Change the following line:
return $company_data->result(); // It return Stc Class Object
to
return $company_data->result_array(); // Now it returns an array
Now you can use array_push() function, it inserts one or more elements to the end of an array.
Or simply use:
$company_data['index'] = value;
Keep your model same return $company_data->result().
In your controller, you need to iterate it for the number of results you get and add new key to your objects.(result() method returns Standard Class Object).
function yourControllerMethod()
{
$company_data = $this->your_model->xxx(search_array, $page, $limit);
if(!empty($company_data)
{
foreach($company_data as $cd)
{
$cd->city_name = "pune"; // or anything you want
}
}
var_dump($company_data);
}
Try this to add new key to your results.
Edit:
You asked that you don't have city_name key in your object.
Yes, you don't have. The above code adds a key in your object.
Just like array.
$temp = array();
$temp["id"] = 1;
In this code, initially the array is empty, the next statement add the id as key in the array.

Custom function in model

I need to generate next number based on month and year. Is this proper way to do it or can it be done differently?
class Foo extends Model
{
public function getNextNumber()
{
$result = DB::select('SELECT COALESCE(MAX(number), 0) + 1 AS number FROM foo AS t2 WHERE MONTH(generated_at) = MONTH(CURDATE()) AND YEAR(generated_at) = YEAR(CURDATE())');
return head($result)->number;
}
}
When create a new record:
$foo = new Foo();
$foo->template = 'template1';
$foo->number = $foo->getNextNumber();
$foo->generated_at = DB::raw('NOW()');
$foo->save();
The query itself is fine as long as you don't have too many records in your table - otherwise I'd follow Joel's suggestion and store current number for given year and month in separate table like
Numbers(year, month, number).
If the Laravel code you provided is something you want to run for every model you create, so I'd suggest using Eloquent model events for that:
//Foo.php
protected static function boot() {
parent::boot();
static::creating(function($foo) {
$foo->number = $foo->getNextNumber();
$foo->generated_at = DB::raw('NOW()');
});
}
You could also make the getNextNumber method static so that you don't need an object to get the next number.

Get enum options in laravels eloquent

In my migration file, I gave my table pages a enum field with 2 possible values (as seen below). My question is, if it's possible to select these values with Laravels Eloquent?
$table->enum('status', array('draft','published'));
There are several Workarounds that I found, but there must be some "eloquent-native" way to handle this. My expected output would be this (that would be perfect!):
array('draft','published')
Thank you in advance!
Unfortunately, Laravel does not offer a solution for this. You will have to do it by yourself. I did some digging and found this answer
You can use that function and turn it into a method in your model class...
class Page extends Eloquent {
public static function getPossibleStatuses(){
$type = DB::select(DB::raw('SHOW COLUMNS FROM pages WHERE Field = "type"'))[0]->Type;
preg_match('/^enum\((.*)\)$/', $type, $matches);
$values = array();
foreach(explode(',', $matches[1]) as $value){
$values[] = trim($value, "'");
}
return $values;
}
}
And you use it like this
$options = Page::getPossibleStatuses();
If you want you can also make it a bit more universally accessible and generic.
First, create a BaseModel. All models should then extend from this class
class BaseModel extends Eloquent {}
After that, put this function in there
public static function getPossibleEnumValues($name){
$instance = new static; // create an instance of the model to be able to get the table name
$type = DB::select( DB::raw('SHOW COLUMNS FROM '.$instance->getTable().' WHERE Field = "'.$name.'"') )[0]->Type;
preg_match('/^enum\((.*)\)$/', $type, $matches);
$enum = array();
foreach(explode(',', $matches[1]) as $value){
$v = trim( $value, "'" );
$enum[] = $v;
}
return $enum;
}
You call this one like that
$options = Page::getPossibleEnumValues('status');
Made a small improvement to lukasgeiter's function. The foreach loop in his answer is parsing the string. You can update the regex to do that for you.
/**
* Retrieves the acceptable enum fields for a column
*
* #param string $column Column name
*
* #return array
*/
public static function getPossibleEnumValues ($column) {
// Create an instance of the model to be able to get the table name
$instance = new static;
// Pulls column string from DB
$enumStr = DB::select(DB::raw('SHOW COLUMNS FROM '.$instance->getTable().' WHERE Field = "'.$column.'"'))[0]->Type;
// Parse string
preg_match_all("/'([^']+)'/", $enumStr, $matches);
// Return matches
return isset($matches[1]) ? $matches[1] : [];
}
This throws an error if the column does not exist. So I added a small check in the code
public static function getPossibleEnumValues ($column) {
// Create an instance of the model to be able to get the table name
$instance = new static;
$arr = DB::select(DB::raw('SHOW COLUMNS FROM '.$instance->getTable().' WHERE Field = "'.$column.'"'));
if (count($arr) == 0){
return array();
}
// Pulls column string from DB
$enumStr = $arr[0]->Type;
// Parse string
preg_match_all("/'([^']+)'/", $enumStr, $matches);
// Return matches
return isset($matches[1]) ? $matches[1] : [];
}
As of L5.17 Eloquent does not include this functionality, instead you need to fall back to native QL. Here's an example that will work with SQL and in one line - returning an array like you asked.
In the spirit of one liner complexity ;)
I threw this in one of my view composers - it fetches the column from the table, explodes it and assembles the values in an array.
I iterate over that in my views using a foreach.
explode (
"','",
substr (
DB::select(" SHOW COLUMNS
FROM ".(new \Namespace\Model)->getTable()."
LIKE 'colName'"
)[0]->Type,
6,
-2
)
);

Comparing 2 objects PHP

i need to compare 2 objects to remove duplicates / find new enteries.
The objects are not identical, but they contain the same username key
Here is the layout
database object
array
[0]db->username
[0]db->something
[1]db->username
[1]db->something
etc
other object
array
[0]ob->username
[0]ob->somethingElse
[1]ob->username
[1]ob->somethingElse
etc
I imagine i can loop one array of objects, and compare the $db[$key]->username with an internal loop of the other object $ob[$key]->username but is there a cleaner way ?
I am looking to remove duplicates
No, there is no cleaner way, you have to loop over the properties. If that are not StdClass objects, I would add a custom compare method to their class:
class Person {
protected $id;
protected $name;
protected $age;
/**
* Compares two persons an returns true if their name
* and age equals.
*/
public function equals(Person $b) {
if($b->name === $this->name && $b->age === $this->age) {
return TRUE;
}
return FALSE;
}
}
Then use it like this:
$personA = DB::getPersonById(1);
$personB = DB::getPersonById(2);
if($personA->equals($personB)) {
echo "They are equal";
}
However, beside from this, why not just removing the duplicates using SQL or even better use unique keys in the DB to avoid duplicates at all?

Categories