Issue configuring an array dynamicaly - php

i have a script but before that i want to explain u something
i an calling a function
$data['cat'] = $this->autoload_model->getTree(0,'td_category');
$data['cat'] = $this->autoload_model->getTree(0,'td_division');
so in the below function
$table = td_category
$table = td_division
public function getTree($pid,$table)
{
$table_data=explode("_",$table);
//$table_data[1] will read category for td_category, division for td_division;
global $sp;
static $arr = array(
'category_id' => array(),
'category_title' => array()
);
}
now if i replace this two lines
'category_id' => array(),
'category_title' => array()
by
$table_data[1].'_id' => array(),
$table_data[1].'_title' => array()
then i am getting error due to the static nature of the array,
but if i delete the static keyword, then it doesnt show any error
how can i keep the static keywod and also get the associative fields dynamicaly base on the $table sent

I am not sure very much but you can try following
static $arr = array();
$arr[$table_data[1].'_id'] = array();
$arr[$table_data[1].'_title'] = array();

You mean something like this?
${$table_data[1]."_title"} => array();

Related

PHP - Put variables with a prefix into array

Is there any way of putting variables into an array? I'm not really sure how else to explain it.
I'm developing a website that works with a game server.
The game exports a file which contains variables such as:
$RL_PlayerScore_CurrentTrail_14911 = "lasergold";
$RL_PlayerScore_HasTrail_14911_LaserGold = 1;
$RL_PlayerScore_Money_14911 = 2148;
I'd like to convert these into an array like
$data = array(
'CurrentTrail_14911' => 'lasergold'
'HasTrail_14911_LaserGold' => '1'
'Money_14911' => '2184'
);
Is there any way I could do this?
Thanks in advance
Include file in scope and then get array of defined vars, excluding globals you don't need.
include('name-of-your-file.php');
$data = get_defined_vars();
$data = array_diff_key($data, array(
'GLOBALS' => 1,
'_FILES' => 1,
'_COOKIE' => 1,
'_POST' => 1,
'_GET' => 1,
'_SERVER' => 1,
'_ENV' => 1,
'ignore' => 1 )
);
You can return an array with all your declared variables, and loop through them cutting off the desired piece of text. You could do something like this:
<?php
//echo your generated file here;
$generatedVars = get_defined_vars();
$convertedArray = array();
foreach($generatedVars as $key=>$var)
{
$key = str_replace("RL_PlayerScore_","",$key);
$convertedArray[$key] = $var;
}
If all game variables are going to begin with 'RL_PlayerScore_', you could use something like that :
$vars = [];
foreach($GLOBALS as $var => $value) {
if(strpos($var, 'RL_PlayerScore_') === 0) {
$vars[$var] = $value;
}
}
$vars will be filled by all your variables.
See #Dagon comment also.

Is there an elegant way to reduce an structure to a simple array?

This is a typical array structure:
$s = array ('etc'=>'etc', 'fields' =>
array (
0 => array (
'name'=>'year', 'description'=>'Year of ...', 'type'=>'integer',
),
1 => array (
'name'=>'label', 'description'=>'Offical short name', type'=>'string',
),
2 => array (
'name' => 'xx', 'description' => 'Xx ...', 'type' => 'string',
)
));
Here is a non-elegant way (or "not so elegant way") to reduce the big array to a simple array containing just one column:
$fields = array();
foreach ($strut['resources'][0]['schema']['fields'] as $r)
$fields[] = $r['name'];
This works, but is it possible to do the same with only one instruction? Perhaps using like array_reduce(), but I not see how.
Here are other typical "elegance PHP problem":
$fieldsByName = array();
foreach ($strut['resources'][0]['schema']['fields'] as $r)
$fields[$r['name']] = array(
'description' =>$r['description'],
'type' =>$r['type']
);
Is there a PHP alternative? The idea here is to use the keyword (name in the example) as an array key, and the other elements as usual fields, so, the generic non-elegant algorithm is
$fieldsByName = array();
foreach ($strut['resources'][0]['schema']['fields'] as $r){
$key = $r['name'];
unset($r['name']);
$fields[$key] = $r;
}
You can use array_column to extract all values with key name into another array
$names = array_column($strut['resources'][0]['schema']['fields'], 'name');
you could put your array thru this function:
function flatten(array $array) {
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
it will result in just a literal sequence of just values of your multidimensional array, like so.
Array
(
[0] => etc
[1] => year
[2] => Year of ...
[3] => integer
[4] => day
[5] => Day of the ...
[6] => string
[7] => xx
[8] => Xx ...
[9] => string
)
then, as you know original structure - you can parse this how needed. 4ex: every third value could be new assoc array's key value that holds an array with arrays of first two values.., or as you wish
array_column is first logical announcement, no surprises there.
Depending on how normalized your data is and how often this issues comes up, you could implement a class around your data. You can use the ArrayAccess, Iterator and Countable to make the change completely transparent, and you would be able to implement helper methods to hide the complexity of fetching data.
Here is an example, just using ArrayAccess:
class Strut implements ArrayAccess {
private $data;
private $fieldsByName = null;
public function __construct($data) {
$this->data = $data;
}
public function fieldsByName() {
//If the result has not already been computed
if($this->fieldsByName === null) {
$this->fieldsByName = array();
foreach($this->data['resources'][0]['schema']['fields'] as $r) {
$this->fieldsByName[ $r['name'] ] = array(
'description' =>$r['description'],
'type' =>$r['type']
);
}
}
return $this->fieldsByName;
}
/**
* ArrayAccess Methods
*/
public function offsetSet($offset, $value) {
$this->data[$offset] = $value;
}
public function offsetExists($offset) {
return isset( $this->data[$offset] );
}
public function offsetUnset($offset) {
unset( $this->data[$offset] );
}
public function offsetGet($offset) {
return isset( $this->data[$offset] ) ? $this->data[$offset] : null;
}
}
Using the above code you should be able to access your data just has you have been, but you also have the option of defining additional accessors in a nice container. Note that you also have to implement the Iterator interface to be able to foreach over your data.
This doesn't address the "elegance" issue of the underlying implementation (the other solutions do a nice job of that), but this way hides the complexity completely.

Can I use an array in PHP as associative and also numbed ?

I have an associative array like this
$imagePaths = array(
'logo' => "logo.jpg",
'facebook-logo' => "facebook-icon.jpg",
'twitter-logo' => "twitter-icon.jpg",
'linkedin' => "linkedIn.jpg"
);
for me to call logo, I use below code
$ClassInstance->imagePaths['logo'];
But I would also like to be able to call it using
$ClassInstance->imagePaths[0];
Is there anyway to do this?
You can achieve this with array_keys():
$keys = array_keys($imagePaths);
$ClassInstance->imagePaths[$keys[0]];
You could store a second array using array_values():
$imagePathsKeyed = array_values($imagePaths);
EDIT: I've expanded the example code to help here
<?php
class SomeObject
{
public $imagePaths;
public $keyedImagePaths;
public function __construct()
{
$this->imagePaths = array(
'logo' => "logo.jpg",
'facebook-logo' => "facebook-icon.jpg",
'twitter-logo' => "twitter-icon.jpg",
'linkedin' => "linkedIn.jpg"
);
$this->keyedImagePaths = array_values($this->imagePaths);
}
}
$classInstance = new SomeObject();
// logo.jpg
echo $classInstance->imagePaths['logo'];
// logo.jpg
echo $classInstance->keyedImagePaths[0];

Get the sub array in a bidimensional array having a particular key/value pair

I have a large PHP array, similar to:
$list = array(
array(
'id' = '3243'
'link' = 'fruits'
'lev' = '1'
),
array(
'id' = '6546'
'link' = 'apple'
'lev' = '2'
),
array(
'id' = '9348'
'link' = 'orange'
'lev' = '2'
)
)
I want to get the sub-array which contains a particular id.
Currently I use the following code:
$id = '3243'
foreach ($list as $link) {
if (in_array($id, $link)) {
$result = $link;
}
}
It works but I hope there is a better way of doing this.
You can
write $link['id']==$id instead of in_array($id, $link) whitch will be less expensive.
add a break; instruction after $result = $link; to avoid useless loops
While this answer wouldn't have worked when the question was asked, there's quite an easy way to solve this dilemma now.
You can do the following in PHP 5.5:
$newList = array_combine(array_column($list,'id'),$list);
And the following will then be true:
$newList[3243] = array(
'id' = '3243';
'link' = 'fruits'; etc...
The simplest way in PHP 5.4 and above is a combination of array_filter and the use language construct in its callback function:
function subarray_element($arr, $id_key, $id_val = NULL) {
return current(array_filter(
$arr,
function ($subarr) use($id_key, $id_val) {
if(array_key_exists($id_key, $subarr))
return $subarr[$id_key] == $id_val;
}
));
}
var_export(subarray_element($list, 'id', '3243')); // returns:
// array (
// 'id' => '9348',
// 'link' => 'orange',
// 'lev' => '2',
// )
current just returns the first element of the filtered array.
A few more online 3v4l examples of getting different sub-arrays from OP's $list.

Accessing deeper array keys using function arguments

I am trying to create a function (unless one already exists?) which is supposed to accept an "unlimited" amount of arguments (using func_get_args()) to find the value of an array key. Regardless of how deep within the array it is to be found.
Say if I would use $registry->getSetting( 'template', 'default' ); I am supposed to get the value of $this->properties['settings']['template']['default'] or if I would you $registry->getSetting( 'users', 1, 'name', 'first' ); I would expect it to return the value of $this->properties['users'][1]['name']['first'] (just a second example with a couple of extra arguments).
Now, to do something like this, I could count the amount of arguments passed using func_num_args() and then do a switch with different cases. Although, this would limit it to a certain amount of keys.
So I am asking you if there is a way of doing this, to allow an "unlimited" amount rather than a fixed amount of arguments to access a deeper key of an array.
<?PHP
class Registry
{
// Values are actually fetched from a config file, but for easier understanding
private $properties = array(
'settings' => array(
'template' => array(
'default' => 'default',
'caching' => TRUE
)
)
);
public function getSetting( )
{
// do something like
// return $this->properties['settings'][func_get_args( )];
}
}
?>
Any help whatsoever is highly appreciated.
Thank you!
<?PHP
class Registry
{
// Values are actually fetched from a config file, but for easier understanding
private $properties = array(
'settings' => array(
'template' => array(
'default' => 'default',
'caching' => TRUE
)
)
);
public function getSetting()
{
$result = $this->properties;
foreach (func_get_args() as $arg) {
if (isset($result[$arg])) {
$result = $result[$arg];
} else {
return;
}
}
return $result;
}
}
$r = new Registry();
var_dump($r->getSetting('settings', 'template', 'default'));
?>
Hmm, I'm not sure if this is what you want, but this is straight from the PHP manual:
Variable-length argument lists
PHP 4 and above has support for
variable-length argument lists in
user-defined functions. This is really
quite easy, using the func_num_args(),
func_get_arg(), and func_get_args()
functions.
No special syntax is required, and
argument lists may still be explicitly
provided with function definitions and
will behave as normal.
I would just loop over the arguments and output them into a single array (I might be misinterpreting your question):
$output = array();
$arguments = func_get_args();
foreach ($argument as $arg)
{
$output[$arg] = $this->properties['settings'][$arg];
}
return $output;
Good luck?
I don't know if there is a PHP function which can do this, but my way is working fine too:
class Registry
{
// Values are actually fetched from a config file, but for easier understanding
private $properties = array(
'settings' => array(
'template' => array(
'default' => 'default',
'caching' => TRUE
)
)
);
public function getSetting( $array = array() )
{
$return = $this->properties['settings'];
foreach( $array as $a )
{
$return = $return[$a];
}
return $return;
}
}
then use:
$Registry = new Registry();
$template = $Registry->getSetting(array( 'template' ) );
$template_caching = $Registry->getSetting(array( 'template', 'caching' ) );
Use dot as separator for nested arrays:
Registry::getAttribute('first.second.1.value'); // will return $ar['first']['second'][1]['value']
In getAttribute explode param by . and map it into registry values.
Something like this (untested):
function getSetting ( /* .. */ )
{
$args = func_get_args();
array_unshift( $args, $this->properties );
return getSettingInternal( $args );
}
function getSettingInternal ( $args )
{
$arr = $args[0];
if ( count( $args ) > 1 )
{
$key = array_slice( $args, 1, 1 );
if ( !is_array( $arr ) )
return $arr;
$arr = array_key_exists( $arr, $key ) ? $arr[$key] : $arr['default'];
$args[0] = $arr;
return getSettingInternal( $args );
}
else
return $arr;
}

Categories