I need to be able to echo a value from a private property in one of my classes if a method is called within the class. It's a little tricky to explain so let me demostrate and hopefully someone can fill in the blank for me :)
<?php
class test {
private $array['teachers']['classes'][23] = "John";
public function __construct($required_array) {
$this->array['teachers']['classes'][23] = "John";
$this->array['students'][444] = "Mary";
$this->echo_array($required_array);
}
public function echo_array($array) {
// Echo the value from the private $this->array;
// remembering that the array I pass can have either
// 1 - 1000 possible array values which needs to be
// appended to the search.
}
}
// Getting the teacher:
$test = new test(array('teachers','classes',23));
// Getting the student:
$test = new test(array('students',444));
?>
Is this possible?
$tmp = $this->array;
foreach ($array as $key) {
$tmp = $tmp[$key];
}
// $tmp === 'John'
return $tmp; // never echo values but only return them
An other approach to get value;
class Foo {
private $error = false,
$stack = array(
'teachers' => array(
'classes' => array(
23 => 'John',
24 => 'Jack',
)
)
);
public function getValue() {
$query = func_get_args();
$stack = $this->stack;
$result = null;
foreach ($query as $i) {
if (!isset($stack[$i])) {
$result = null;
break;
}
$stack = $stack[$i];
$result = $stack;
}
if (null !== $result) {
return $result;
}
// Optional
// trigger_error("$teacher -> $class -> $number not found `test` class", E_USER_NOTICE);
// or
$this->error = true;
}
public function isError() {
return $this->error;
}
}
$foo = new Foo();
$val = $foo->getValue('teachers', 'classes', 24); // Jack
// $val = $foo->getValue('teachers', 'classes'); // array: John, Jack
// $val = $foo->getValue('teachers', 'classes', 25); // error
if (!$foo->isError()) {
print_r($val);
} else {
print 'Value not found!';
}
Related
I have a code that get categories from database but I don't know how to get all subcategories(parents).
This my php code :
function get_the_category($allCats,$filter_id = null) {
$re_struct_cat = array();
$filter_id = 10;
$ids = array();
$xx = array();
foreach($allCats as $cat_key=>$cat_val) {
$re_struct_cat[$cat_val["id"]] = array(
"title" => $cat_val["cat_title"],
"parent" => $cat_val["cat_parent"],
);
$ids = array_merge($ids,array($cat_val["id"]));
}
foreach($ids as $k=>$v) {
if($re_struct_cat[$v]["parent"]) {
$xx[] = $re_struct_cat[$re_struct_cat[$v]["parent"]];
}
}
return $xx;
//return $re_struct_cat;
//print_r($re_struct_cat);
}
What I want exactly
I have table with 3 columns [id,title,parent]
ID TITLE PARENT
1 Science 0
2 Math 1
3 Algebra 2
4 Analyse 2
5 Functions 4
So if variable filter_id = 10 I got cat_parent = 4
So I want to take that value and looking for it in array and if find another cat_parent do the same thing until find 0 or null value
It is not the most optimal solution, but you can use iterators.
Firstly, create the custom iterator, that can handle categories:
class AdjacencyListIterator extends RecursiveArrayIterator
{
private $adjacencyList;
public function __construct(
array $adjacencyList,
array $array = null,
$flags = 0
) {
$this->adjacencyList = $adjacencyList;
$array = !is_null($array)
? $array
: array_filter($adjacencyList, function ($node) {
return is_null($node['parent']);
});
parent::__construct($array, $flags);
}
private $children;
public function hasChildren()
{
$children = array_filter($this->adjacencyList, function ($node) {
return $node['parent'] === $this->current()['id'];
});
if (!empty($children)) {
$this->children = $children;
return true;
}
return false;
}
public function getChildren()
{
return new static($this->adjacencyList, $this->children);
}
}
It is taken from my another answer.
Then you can simply loop over this iterator until you find the needed id:
$id = 5;
$categories = [];
$result = null;
foreach ($iterator as $node) {
$depth = $iterator->getDepth();
$categories[$depth] = $node['categoryname'];
if ($node['id'] === $id) {
$result = array_slice($categories, 0, $depth + 1);
break;
}
}
Here is the demo.
Can we copy all the dynamic values to array for eg:
I have a function like this
<?php
$list_a = array(); //defining an array
$list_b = array();
$list_c = array();
addText($a,$b,$c)
{
$list_a[] = $a;
$list_b[] = $b;
$list_c[] = $c;
}
I will pass different values to addText() function after that I have to access those inserted value using foreach from another function.
How can we do that .
Just define your php variable as global.
Eg. global $list_a,$list_b,$list_c;
When you are using that variable in any function then first declare above variables in that function.
Eg:
addText($a,$b,$c)
{
global $list_a,$list_b,$list_c;
$list_a[] = $a;
$list_b[] = $b;
$list_c[] = $c;
}
To accomplish this you have to use concept of global variable
Try this:
$list_a = array(); //defining an array
$list_b = array();
$list_c = array();
function addText($a,$b,$c)
{
global $list_a, $list_b, $list_c;
array_push($list_a,$a);
array_push($list_b,$b);
array_push($list_c,$c);
}
addText('12','23',12);
echo '<pre>';
print_r($list_a);
print_r($list_b);
print_r($list_c);
This would work but it is bad design. See here why.
<?php
$list_a = array(); //defining an array
$list_b = array();
$list_c = array();
function addText($a,$b,$c)
{
global $list_a, $list_b, $list_c;
$list_a[] = $a;
$list_b[] = $b;
$list_c[] = $c;
}
function foreachThem()
{
global $list_a, $list_b, $list_c;
foreach($list_a as $item)
{
//...
}
foreach($list_b as $item)
{
//...
}
foreach($list_c as $item)
{
//...
}
}
A better way would be saving them in a parent array (this is optional but it reduces the amount of parameters and therefor the amount of code) and passing it as reference. See here for info on passing by reference.
<?php
$theLists = array(
"a" => array(),
"b" => array(),
"c" => array()
);
// note the '&'
function addText(&$lists, $a,$b,$c)
{
$lists["a"][] = $a;
$lists["b"][] = $b;
$lists["c"][] = $c;
}
// '&' is not needed here
function foreachThem($lists)
{
foreach($lists["a"] as $item)
{
//...
}
foreach($lists["b"] as $item)
{
//...
}
foreach($lists["c"] as $item)
{
//...
}
}
Try this,
<?php
$list_a = array(); //defining an array
$list_b = array();
$list_c = array();
addText($a,$b,$c)
{
$list_a[] = $a;
$list_b[] = $b;
$list_c[] = $c;
}
public function 'function_name'($list_a, $list_b, $list_c) {
foreach ($list_a as $list) {
echo $list;
}
}
Let's say I have an array of objects.
<?php
$people = array();
$people[] = new person('Walter Cook');
$people[] = new person('Amy Green');
$people[] = new person('Irene Smith');
How can I search an object in this array for a certain instance variable? For example, let's say I wanted to search for a person object with the name of "Walter Cook".
Thanks in advance!
It depends of the person class construction, but if it has a field name that keeps given names, you can get this object with a loop like this:
for($i = 0; $i < count($people); $i++) {
if($people[$i]->name == $search_name) {
$person = $people[$i];
break;
}
}
Here is:
$requiredPerson = null;
for($i=0;$i<sizeof($people);$i++)
{
if($people[$i]->name == "Walter Cook")
{
$requiredPerson = $people[$i];
break;
}
}
if($requiredPerson == null)
{
//no person found with required property
}else{
//person found :)
}
?>
Assuming that name is a public property of the person class:
<?php
// build the array of objects
$people = array();
$people[] = new person('Walter Cook');
$people[] = new person('Amy Green');
$people[] = new person('Irene Smith');
// search name
$searchName = 'Walter Cook';
// ascertain the presence of the name in the array of objects
$isMatch = false;
foreach ($people as $person) {
if ($person->name === $searchName) {
$isMatch = true;
break;
}
}
// alternatively, if you want to return all matches into
// a new array of $results you can use array_filter
$result = array_filter($people, function($person) use ($searchName) {
return $person->name === $searchName;
});
hope this helps :)
well you could try this inside your class
//the search function
function search_array($array, $attr_name, $attr_value) {
foreach ($array as $element) {
if ($element -> $attr_name == $attr_value) {
return TRUE;
}
}
return FALSE;
}
//this function will test the output of the search_array function
function test_Search_array() {
$person1 = new stdClass();
$person1 -> name = 'John';
$person1 -> age = 21;
$person2 = new stdClass();
$person2 -> name = 'Smith';
$person2 -> age = 22;
$test = array($person1, $person2);
//upper/lower case should be the same
$result = $this -> search_array($test, 'name', 'John');
echo json_encode($result);
}
how to print dynamical add properties in bellow class?
class Car {
function __construct() {
}
function setInfo($car_arr) {
foreach ($car_arr as $key => $value) {
$this->{$key} = $value;
}
}
}
set class object like bellow
$car1 = new Car();
$car1->setInfo(array('make' => 'Toyota', 'model' => 'scp10'));
$car2 = new Car();
$car2->setInfo(array('anme1' => 'value1', 'anme2' => 'value2'));
now I want to to print car object bellow
make = Toyota
model = scp10
Try :
$car1 = new Car();
$car1->setInfo(array('make' => 'Toyota', 'model' => 'scp10'));
echo $car1->make;
echo $car1->model;
<?php
class Car {
function __construct() {
}
function setInfo($car_arr) {
foreach ($car_arr as $key => $value) {
$this->{$key} = $value;
}
}
}
$car1 = new Car();
$car1->setInfo(array('make' => 'Toyota', 'model' => 'scp10'));
echo "Make value is : " . $car1->make. ", Model value is : ". $car1->model;
?>
above code output Make value is : Toyota, Model value is : scp10
Please consider storing the properties explicitly like I pointed out in this answer:
<?php
class Car {
private $data = array();
function setInfo(array $carInfo) {
foreach ($carInfo as $k => $v) {
$this->data[$k] = $v;
}
return $this;
}
function __set($key, $val) {
$this->data[$key] = $val;
}
function __get($key) {
return $this->data[$key];
}
}
$car = new Car();
$car->setInfo(array('make' => 'Toyota', 'warranty' => '5 years'));
I'd consider it more "clean", but that's probably debatable.
I think you look for something like this PHP Magic Methods
For example this one:
<?php
class A
{
public $var1;
public $var2;
public static function __set_state($an_array) // As of PHP 5.1.0
{
$obj = new A;
$obj->var1 = $an_array['var1'];
$obj->var2 = $an_array['var2'];
return $obj;
}
}
$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';
eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
// 'var1' => 5,
// 'var2' => 'foo',
// ));
var_dump($b);
?>
This will be helpful too.
You can fetch all properties using get_object_vars():
$vars = get_object_vars($car1);
foreach ($vars as $key => $value) {
echo $key . ' = ' . $value . '<br />';
}
I would like to split an array:
$o = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
based on the color attribute of each item, and fill corresponding sub arrays
$a = array("green", "yellow", "blue");
function isGreen($var){
return($var->color == "green");
}
$greens = array_filter($o, "isGreen");
$yellows = array_filter($o, "isYellow");
// and all possible categories in $a..
my $a has a length > 20, and could increase more, so I need a general way instead of writing functions by hand
There doesn't seem to exist a function array_split to generate all filtered arrays
or else I need a sort of lambda function maybe
You could do something like:
$o = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
$greens = array_filter($o, function($item) {
if ($item->color == 'green') {
return true;
}
return false;
});
Or if you want to create something really generic you could do something like the following:
function filterArray($array, $type, $value)
{
$result = array();
foreach($array as $item) {
if ($item->{$type} == $value) {
$result[] = $item;
}
}
return $result;
}
$o = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
$greens = filterArray($o, 'color', 'green');
$yellows = filterArray($o, 'color', 'yellow');
In my second example you could just pass the array and tell the function what to filter (e.g. color or some other future property) on based on what value.
Note that I have not done any error checking whether properties really exist
I would not go down the road of creating a ton of functions, manually or dynamically.
Here's my idea, and the design could be modified so filters are chainable:
<?php
class ItemsFilter
{
protected $items = array();
public function __construct($items) {
$this->items = $items;
}
public function byColor($color)
{
$items = array();
foreach ($this->items as $item) {
// I don't like this: I would prefer each item was an object and had getColor()
if (empty($item->color) || $item->color != $color)
continue;
$items[] = $item;
}
return $items;
}
}
$items = json_decode('[{"id":"1","color":"green"},{"id":"2","color":"green"},{"id":"3","color":"yellow"},{"id":"4","color":"green"}]');
$filter = new ItemsFilter($items);
$greens = $filter->byColor('green');
echo '<pre>';
print_r($greens);
echo '</pre>';
If you need more arguments you could use this function:
function splitArray($array, $params) {
$result = array();
foreach ($array as $item) {
$status = true;
foreach ($params as $key => $value) {
if ($item[$key] != $value) {
$status = false;
continue;
}
}
if ($status == true) {
$result[] = $item;
}
}
return $result;
}
$greensAndID1 = splitArray($o, array('color' => 'green', 'id' => 1));