getting warning when use in_array and multidimensional-array - php

I make a array and fill it by variables(index and value) by code in php(yii framework). but my program don't work good.I cannot use my array after fill.
in model Lookup.php
private static $row_flags= array();
private static $table_flags= array();
public static function checkStatus($value,$row,$column) {
$thresholds= hreshold::model()->findAll(array('select'=>$row.','.$column));
self::$row_flags['browsing'][$row][$column]=($value < $thresholds[0]->$row) ?"green":(($value > $thresholds[0]->$column)?"red":"yellow");
return self::$row_flags['browsing'][$row][$column];
}
public static function getRowFlag() {
return self::$row_flags;
}
public static function row_color($table,$row){
return in_array("yellow",self::$row_flags['browsing'][$row]);
}
view.php
<?php
lookup::checkStatus(3001,'http','access');
lookup::checkStatus(3001,'http','access');
lookup::checkStatus(3001,'http','core');
lookup::checkStatus(3001,'http','blackbox');
lookup::checkStatus(3001,'http','gateway');
lookup::checkStatus(3001,'http','internet');
print_r(lookup::getRowFlag());
?>
Array
(
[browsing] => Array
(
[http] => Array
(
[access] => yellow
[core] => yellow
[blackbox] => yellow
[gateway] => yellow
[internet] => yellow
)
)
)
if I call Lookup::row_color('browsing','http') in view I have
warning: in_array() expects parameter 2 to be array, null given

Maybe column is the troublemaker:
Instead of l(array('select'=>$row.','.$column));
Use l(array('select'=>$row.','.'select'=>$column));

Use this:
public static function row_color($table,$row){
if (is_array(self::$row_flags['browsing'][$row])) {
return in_array("yellow",self::$row_flags['browsing'][$row]);
}
return FALSE;
}

Related

Accessing the properties of an object of an object dynamically in PHP

Given that I'm getting different object results depending of the API I query, here are two examples out of 35 I have to implement:
stdClass Object
(
[mid] => 7127.75
[bid] => 7126.6
[ask] => 7128.9
[last_price] => 7128.8
[low] => 7000.0
[high] => 7492.1
[volume] => 53255.4195502
[timestamp] => 1510265647.9803913
)
stdClass Object
(
[Success] => 1
[Message] =>
[Data] => stdClass Object
(
[AskPrice] => 7095
[BidPrice] => 7070
[Low] => 7001
[High] => 7540
[Volume] => 17.38943459
[LastPrice] => 7090
[Change] => -1.02
[Open] => 7163
[Close] => 7090
)
[Error] =>
)
I want to build mapping variable array to access the object easily.
$xmap["a"]["bid"] = "bid";
$xmap["b"]["bid"] = "Data->BidPrice";
Let's assume $content has the first example object, this will work:
print $content->{$xmap["a"]["bid"]}; // the result is 7128.9
As for the second example object, it does not:
print $content->{$xmap["b"]["bid"]}; // the result is PHP Notice: Undefined property: stdClass::$Data->BidPrice in ...
Can this be done or am I stuck with if statements!
First, convert all the objects into assoc. arrays by using json_encode/decode. You'll find this code multiple times here in stackoverflow
$arr = json_decode(json_encode($obj), true);
Second, I recommend a dot-notation for the key-path, plus a tiny function to find the value in a multidimensional array.
Example:
function fromArray($key, $arr) {
$keys = explode('.', $key);
foreach($keys as $k) {
if (!isset($arr[$k]))
return array(); // return empty array
$arr = $arr[$k];
}
return $arr; // can be a scalar value or array
}
$key = 'my.super.array.content';
$array = ['my' => [
'super' => [
'array' =>[
'content'=>4711
]
]
]
];
var_dump($array, fromArray($key, $array));
/*
array(1) {
["my"]=>
array(1) {
["super"]=>
array(1) {
["array"]=>
array(1) {
["content"]=>
int(4711)
}
}
}
}
int(4711)
*/
I found the dot-notation very useful when dealing with complex structures.
You can convert your objects to arrays and build a large mapping array that needs to be maintained and then explode it and loop through it to access the other arrays; or you can try using patterns. I'm thinking Adapter, but maybe another is a better fit. This is using your second object as an example, but just add as many as needed:
class ContentAdapter {
public function __get($name) {
return $this->obj->{$xmap[$name]};
}
}
class ContentAdapter_API_B extends ContentAdapter {
public $xmap = ['bid' => 'BidPrice', 'ask' => 'AskPrice'];
public function __construct($obj) {
$this->obj = $obj->data;
}
}
Now it is consistant regardless of the object since each has an adapter:
$content = new ContentAdapter_API_B($content);
echo $content->bid;
Using your first object you can either create a child as well (ContentAdapter_API_A in case the structure ever changes) or instantiate directly:
$content = new ContentAdapter($content);
echo $content->bid;
Or obviously just use it as is:
echo $content->bid;
An alternate way without inheritance is to use getters:
class ContentAdapter_API_B {
public function __construct($obj) {
$this->obj = $obj->data;
}
public function getBid() { return $this->obj->BidPrice; }
}
So long as the methods are consistent then it will always work:
$content = new ContentAdapter_API_B($content);
echo $content->getBid;

Anonymous function returns class properties? PHP

I was reading a WordPress tutorial in which the author used something like this (I simplified it):
class WPObject {
public $ID;
public $title;
public $content;
public $status;
public function __construct($wp_post) {
$modifiers = [
'key' => function($k, $v) {
return (substr($k, 0, 5) === "post_") ? substr($k, 5) : $k;
}
];
}
}
The function is supposed to remove the post_ prefix from the wp queried object. The question I have is regarding the function I posted above. That anonymous function seems to return an object with with the properties. When I did a print_r on it I get...
Array
(
[key] => Closure Object
(
[this] => WPObject Object
(
[ID] =>
[title] =>
[content] =>
[status] =>
)
[parameter] => Array
(
[$k] =>
[$v] =>
)
)
)
I'm still learning about anonymous functions and was wondering how/why it does this? If you call an anonymous function from an object, does it create an instance of that object or something?
Also, sorry if I'm using incorrect terminology. Don't have anonymous functions, closures, lambda functions straightened out yet.
Not a new instance, it has a reference to the same object in which it is created since PHP 5.4 I believe. So the closure itself can call properties or methods on that class as if being in that class.
class foo {
public $bar = 'something';
function getClosure(){
return function(){
var_dump($this->bar);
};
}
}
$object = new foo();
$closure = $object->getClosure();
//let's inspect the object
var_dump($object);
//class foo#1 (1) {
// public $bar =>
// string(9) "something"
//}
//let's see what ->bar is
$closure();
//string(9) "something"
//let's change it to something else
$object->bar = 'somethingElse';
//closure clearly has the same object:
$closure();
//string(13) "somethingElse"
unset($object);
//no such object/variables anymore
var_dump($object);
//NULL (with a notice)
//but closure stills knows it as it has a reference
$closure();
//string(13) "somethingElse"

PHP SimpleHTMLDom & Php PThreads - Find not finding?

Hopefully someone can shed some light on this,
This is launched within a 'worker' thread of php pthreads package.
I load a page using $html = file_get_html("http://www.google.com/");
If I print_r($html) at this point I get :
simple_html_dom Object
(
[root:simple_html_dom:private] => simple_html_dom_node Object
(
[nodetype] => 5
[tag:simple_html_dom_node:private] => text
[attr:simple_html_dom_node:private] => Array
(
[tag] => root
)
[children:simple_html_dom_node:private] => simple_html_dom_node Object
(
[nodetype] => 1
[tag:simple_html_dom_node:private] => html
[attr:simple_html_dom_node:private] => Array
(
)
[children:simple_html_dom_node:private] => simple_html_dom_node Object
(
[nodetype] => 1
[tag:simple_html_dom_node:private] => head
[attr:simple_html_dom_node:private] => Array
(
)...
Then if I try $html->find('a',0), $html->find('a') or even something like $html->find('head'), and print the result, I always get an empty Array.
class Product extends Stackable{
function __construct($prod_id,$link)
{
$this->prod_id=$prod_id;
$this->link=$link;
}
public function get_data($country)
{
//AMAZON API XML REQUEST
return $xml; //XML file
}
public function parse_data($xml)
{
$product = array();
//PARSE PRODUCT XML INTO ARRAY
return $product;
}
public function update_price($product)
{
$html = file_get_html($this->link);
print_r ($html->find('a'));
}
public function run()
{
$xml = $this->get_data('US');
$product = $this->parse_data($xml);
$this->update_price($product);
}
}
$product = new Product(ID,URL);
$worker = new Worker();
$worker->start();
$worker->stack($product);
What could be the issue?
Thanks in advance for any help.

Get a PHPActiveRecord result as simple array, not array of objects

I would like to have a simple a method, that can give back PHP Activerecord results as simple/associative arrays, not an array of ActiveRecord Objects.
In Ruby I believe this is done perhaps with .map() method. (I am not a Ruby guy...)
What I want is a simple method call, like toArray() in Zend_DB_Table, not a foreach, or something like that, but I can't seem to find it in their docs.
In PHP ActiveRecord getting a result is really easy:
$settings = SystemSettings::all();
But it gives back something like this:
[0] => SystemSettings Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[param] => author
[value] => Hawle
)
[__dirty:ActiveRecord\Model:private] => Array
(
)
[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)
[__new_record:ActiveRecord\Model:private] =>
)
[1] => SystemSettings Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[param] => base_url
[value] => example.com
)
[__dirty:ActiveRecord\Model:private] => Array
(
)
[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)
[__new_record:ActiveRecord\Model:private] =>
)
While this is really great in many cases, here, I would just like to have a simple array, like this:
Array
(
[author] => Hawle
[base_url] => example.com
)
I had a similar issue hopefully this can help someone else who stumbles on it. Obviously, this is specific to phpactiverecord.org.
In /lib/Model.php I added the following function:
public function to_array(array $options=array())
{
return $this->serialize('array', $options);
}
In /lib/Serialization.php I added the following class
class arraySerializer extends Serialization
{
public static $include_root = false;
public function to_s()
{
return self::$include_root ? array(strtolower(get_class($this->model)) => $this->to_a()) : $this->to_a();
}
}
I can then call ->to_array() and get an array back.
Hope this helps!
I was searching for the answer to this question in order to produce an array of results that could be easily json-encoded and sent as the response to an ajax call. I wanted only the attributes of each object in the array of results.
Unfortunately, you can't just call to_json() on each result and then json-encode the entire thing; you end up with double-encoding. Fortunately, though, the function and class posted by #willwashburn to solve this problem have now been included in php-activerecord, though they don't seem to have made it into the online documentation.
To return an array of results, do the following:
$data = MyModel::find('all');
foreach ($data as &$result) {
$result = $result->to_array();
}
Your entire result set will now be an array of arrays, containing only the attributes of each object. You can then do something like
echo(json_encode($data));
if you want to send it as the response to an ajax call.
This is my solution:
$posts = Post::find('all');
$arrayResult = array_map(function($res){
return $res->attributes();
}, $posts);
printf('<pre>%s</pre>', print_r($arrayResult, true));
class MyPHPActiveRecord extends PHPActiveRecord {
public function toJSON() {
return json_encode(get_object_vars($this));
}
}
You could do it like this:
funciton ar2array($settings){
$arr = array();
foreach($settings as $fieldObj){
$fieldName = $fieldObj->attributes["param"];
$fieldValue = $fieldObj->attributes["value"];
$arr[$fieldName] = $fieldValue;
}
return $arr;
}
$resultAsYouWant = ar2array($settings);
Hope this helps. Cheers
PS: If ->attributes is private use its accesor method (there must be one) as ->getAttributes() or equivalent.
I found this looking for solution of the same problem that I encountered using Yii framework - there is simplier way to do this in Yii.
$posts = Posts::model()->findAll();
foreach($posts as $result)
{
print_r($result->attributes);
}
It prints simple array as requested:
Array
(
[id] => 1
[title] => Title
[text] => Text
)
Hope it helps somebody.
My solution:
Added the following method to the utils class found in lib\Utils.php
public static function results_to_json($data)
{
$arr = array();
if(count($data)>0){
foreach($data as $row){
array_push($arr, $row->to_array());
}
}
return json_encode($arr);
}
Call by:
echo \ActiveRecord\Utils::results_to_json($dataobject);
Obviously this is no longer relevant to the OP; however, considering that it still took me over an hour to find a solution for this (no thanks to php-activerecords docs), this may help someone else.
$r = Model::find('$id')->attributes();
$a = [];
foreach ($r as $k => $v)
{
$a[$k] = $v;
}
Perhaps not the most elegant, but works perfectly.

PHP - get_class_methods() Problem

I've this sample code:
class A
{
public function A_A() { /* ... */ }
public function A_B() { /* ... */ }
}
class B extends A
{
public function B_A() { /* ... */ }
public function B_B() { /* ... */ }
public function B_C()
{
return get_class_methods($this);
}
}
$a = new A();
$b = new B();
Doing this:
echo '<pre>';
print_r($b->B_C());
echo '</pre>';
Yields the following output:
Array
(
[0] => B_A
[1] => B_B
[2] => B_C
[3] => A_A
[4] => A_B
)
How can I make it return only the following methods?
Array
(
[0] => B_A
[1] => B_B
[2] => B_C
)
I've a method in class A that should call all the methods in class B, the problem is of course that it leads to a infinite loop due to the values returned by get_class_methods().
You might need full strength Reflection. However, before you go there, it might be worth trying something like this.
array_diff(get_class_methods($this), get_class_methods(get_parent_class($this)))
You can't. Part of the functionality of extending a class is that you get all of the methods of the class you extended, in the new class, identical to as if you defined them in the new class itself.

Categories