I'm constructing a gallery which will use the URI to define a set of filter settings. CodeIgniter's ruri_to_assoc() works brilliantly for the majority of my settings as they are as simple as key=>value. However, one value (tags) can contain a number of values that I wish to match against.
As ruri_to_assoc() works off a key/val pairing, how would I set an array to a key in the url? Example:
/days/365/order/oldest/tag/car/tag/red/tag/mustang
At the moment, it looks like I'm going to have to explode the uri_string() and cycle through it myself. Like so:
$test_fil = explode('/',$this->uri->uri_string());
unset($test_fil[0]);
$val = 'key';
foreach($test_fil as $fkey=>$fval){
if($fval=='tags'){
$val = 'tag';
$new_filter['tags'] = '';
}
else{
if($val == 'key'){
$new_filter[$fval] = '';
$val = 'val';
$current_key = $fval;
}
elseif($val == 'val'){
$new_filter[$current_key] = $fval;
$val = 'key';
}
else{
$new_filter['tags'][] = $fval;
}
}
}
Is there something in CI that can do this for me?
We just need to make sure that uri_to_assoc will not override already existing keys when building the array.
In application/core create MY_URI.php :
class MY_URI extends CI_URI
{
protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
{
if ( ! is_numeric($n))
{
return $default;
}
if (isset($this->keyval[$which], $this->keyval[$which][$n]))
{
return $this->keyval[$which][$n];
}
$total_segments = "total_{$which}s";
$segment_array = "{$which}_array";
if ($this->$total_segments() < $n)
{
return (count($default) === 0)
? array()
: array_fill_keys($default, NULL);
}
$segments = array_slice($this->$segment_array(), ($n - 1));
$i = 0;
$lastval = '';
$retval = array();
foreach ($segments as $seg)
{
/*HERE IS THE PART WE TRULY OVERRIDE*/
if ($i % 2)
{
if(is_array($retval[$lastval]))
$retval[$lastval][] = $seg;
else
$retval[$lastval] = $seg;
}
else
{
if(isset($retval[$seg]) && !is_array($retval[$seg]))
{
$tmp = $retval[$seg];
$retval[$seg] = array();
$retval[$seg][] = $tmp;
}
else if(!isset($retval[$seg]))
{
$retval[$seg] = NULL;
$lastval = $seg;
}
}
/*END OVERRIDE*/
$i++;
}
if (count($default) > 0)
{
foreach ($default as $val)
{
if ( ! array_key_exists($val, $retval))
{
$retval[$val] = NULL;
}
}
}
// Cache the array for reuse
isset($this->keyval[$which]) OR $this->keyval[$which] = array();
$this->keyval[$which][$n] = $retval;
return $retval;
}
}
And then in your controller, nothing change :
$myTags = $this->uri->uri_to_assoc();
Here is what I get after testing :
array (size=3)
'days' => string '365' (length=3)
'order' => string 'oldest' (length=6)
'tag' =>
array (size=3)
0 => string 'car' (length=3)
1 => string 'red' (length=3)
2 => string 'mustang' (length=7)
Related
I'm looking for an easy solution to create a little function to merge two arrays with value concat (I'm using it to create html tag attribute):
$default["class"] = "red";
$new["class"] = "green";
$new["style"] = "display:block"
The result:
$res["class"] = "red green";
$res["style"] = "display: block";
and one more option:
if the $new is not an array, just concat with the $default["class"] (if this exist), and the other side: if the $default is a simple string, convert to array: $default["class"] = $default;
I created a function but would like to use an easier, shorter way for that:
function attrMerge( $default, $new="" ){
$res = array();
if(!is_array($default)) {
$res["class"] = $default;
}
else {
$res = $default;
}
if( $new !== "" ){
if(!is_array($new)) {
if(isset($res["class"])){
$res["class"].= " ".$new;
}
}
else {
foreach($new as $key=>$value) {
if( isset($res[$key]) ) {
$res[$key].= " ".$value;
}
else {
$res[$key] = $value;
}
}
}
}
return $res;
}
$a = attrMerge("red", array("class"=>"green", "style"=>"display: block;"));
I think this is the function that you need. I have initialised the css classes and styles as empty and in depends what you pass into the function then you get the relevant array
/**
* This function returns an array of classes and styles
*
* #param $default
* #param $new
* #return array
*/
function attrMerge($default=null, $new=nul)
{
$result = array();
$result['class'] = "";
$result['style'] = "";
// add default class if exists
if (!empty($default) && is_string($default)) {
// $default is string
$result['class'] = $default;
}
if (!empty($default)
&& is_array($default)
) {
if (array_key_exists('class', $default)
&& !empty($default['class'])
) {
// $default['class'] exists and it's not empty
$result['class'] = $default['class'];
}
if (array_key_exists('style', $default)
&& !empty($default['style'])
) {
// $default['style'] exists and it's not empty
$result['style'] = $default['style'];
}
}
// add additional classes OR styles
if (!empty($new)) {
if(!is_array($new)) {
$result['class'] = empty($result['class'])
? $new
: $result['class'] . " " . $new;
} else {
foreach ($new as $key => $value) {
if (isset($result[$key])) {
$result[$key] = empty($result[$key])
? $value
: $result[$key] . " " . $value;
} else {
$result[$key] = $value;
}
}
}
}
return $result;
}
A way I believe suits your need, hopefully it's as adaptable and effecient as you were expecting.
$array1 = array(
'class' => 'class1',
'style' => 'display: none;'
);
$array2 = array(
'class' => 'class2'
);
$arrayFinal = arrayMerge($array1, $array2);
var_dump($arrayFinal);
function arrayMerge($arr1, $arr2 = ''){
// Array of attributes to be concatenated //
$attrs = array('class');
if(is_array($arr2)){
foreach($attrs as $attr){
if(isset($arr1[$attr]) && isset($arr2[$attr])){
// Not using .= to allow for smart trim (meaning empty check etc isn't needed //
$arr1[$attr] = trim($arr1[$attr] . ' ' . $arr2[$attr]);
}
}
}else{
$arr1['class'] = trim($arr1['class'] . ' ' . $arr2);
}
return $arr1;
}
$def = ['class' => 'red'];
$new = ['class' => 'green', 'style' => 'style'];
function to_array($in) {
return is_array($in) ? $in : ['class' => $in];
}
$def = to_array($def);
$new = to_array($new);
$res = $def;
array_walk($new, function ($val, $key) use (&$res) {
$res[$key] = trim(#$res[$key] . ' ' . $val);
});
var_dump($res);
I'm trying to solve a somewhat simple task but can't wrap my head around doing it without a lot of loops and messy code.
I want all to print all combinations of the array below:
$product = array(
array
(
'1X'
),
array
(
'X2'
)
);
producing the following result:
//ROW 1
1
X
//ROW 2
X
2
//ROW 3
1
2
//ROW 4
X
X
this work:
$product = array(
array
(
'1WQ'
),
array
(
'3'
),
array
(
'X'
)
);
//
class Combine{
private $product = array();
private $result = array();
private $format = array();
public function __construct($p=array()){
$this->product = $p;
}
public function process(){
foreach($this->product as $k=>$v){
$this->format[] = str_split($v[0]);
}
$this->result = $this->build();
return $this;
}
public function build()
{
if (!$this->format) {
return array(array());
}
$sub = array_shift($this->format);
$c = $this->build($this->format);
$res = array();
foreach ($sub as $v) {
foreach ($c as $p) {
array_unshift($p, $v);
$res[] = $p;
}
}
return $res;
}
public function response(){
return $this->result;
}
}
//
$combine = new Combine($product);
$resp = $combine->process()->response();
var_dump($resp);
function helperFunction($array, $index, $workArray)
{
$tempArray = array();
$tmpStr = $array[$index][0];
// loop over the current array characters
for( $i = 0; $i < strlen($tmpStr); $i++ )
{
$char = substr($tmpStr, $i, 1);
// first time - add characters to the work array
if (count($workArray) == 0)
{
$tempArray[] = $char;
}
// later round - add characters to existing items
else
{
foreach ($workArray as $workItem)
{
$tempArray[] = $workItem . $char;
}
}
}
// last round
if (count($array) == $index + 1)
{
return $tempArray;
}
// recursion round
else
{
return helperFunction($array, $index + 1, $tempArray);
}
}
$result = helperFunction($product, 0, array());
$arr['animal'][0] = 'Dog';
$arr['animal'][1] = 'Cat';
From that array basically I need to create a function with the array value parameter and then it gives me the array keys.
For example:
find_index('Cat');
Output :
The result is animal, 1
You could probably do something like
function find_index($value) {
foreach ($arr as $index => $index2) {
$exists = array_search($value, $index2);
if ($exists !== false) {
echo "The result is {$index}, {$exists}";
return true;
}
}
return false;
}
Try this:
$arr['animal'][0] = 'Dog';
$arr['animal'][1] = 'Cat';
function find_index($searchVal, $arr){
return array_search($searchVal, $arr);
}
print_r(find_index('Cat', $arr['animal']));
Consider this Array,
$arr['animal'][] = 'Dog';
$arr['animal'][] = 'Cat';
$arr['insects'][] = 'Insect1';
$arr['insects'][] = 'Insect2';
Here is Iterator Method,
$search = 'InsectSub1';
$matches = [];
$arr_array = new RecursiveArrayIterator($arr);
$arr_array_iterator = new RecursiveIteratorIterator($arr_array);
foreach($arr_array_iterator as $key => $value)
{
if($value === $search)
{
$fill = [];
$fill['category'] = $arr_array->key();
$fill['key'] = $arr_array_iterator->key();
$fill['value'] = $value;
$matches[] = $fill;
}
}
if($matches)
{
// One or more Match(es) Found
}
else
{
// Not Found
}
$arr['animal'][] = 'Dog';
$arr['animal'][] = 'Cat';
$arr['insects'][] = 'Insect1';
$arr['insects'][] = 'Insect2';
$search_for = 'Cat';
$search_result = [];
while ($part = each($arr)) {
$found = array_search($search_for, $part['value']);
if(is_int($found)) {
$fill = [ 'key1' => $part['key'], 'key2' => $found ];
$search_result[] = $fill;
}
}
echo 'Found '.count($search_result).' result(s)';
print_r($search_result);
This function should iterate through multidimensional array and return collection of array's element_rule_id values. Hovewer it's not returning anything.
You can check var_dump of array here: http://pastebin.com/T5nwGmna
function deepIns($array = array(), $collect = array(), $str = '') {
$count = count($array);
foreach($array as $i => $val) {
if(is_array($val)) {
if(array_key_exists('element_rule_id' ,$val)) {
$collect[$val['element_rule_id']] = 1;
}
if(($count - 1) == $i) {
if(array_key_exists('0', $val['condition'])) {
deepIns($val['condition'], $collect);
}
else {
return $collect;
}
}
}
}
}
Expected result would be:
array (size=5)
'rule_demo_rules1_1' => int 1
'rule_demo_rules1_2' => int 1
'rule_demo_rules1_3' => int 1
'rule_demo_rules1_5' => int 1
'rule_demo_rules1_6' => int 1
In desining of recursive functions, returning is ambigous way, simple solution is to put your function in an static class, and add the return results into that class:
class xx {
public static $result;
function deepIns($array = array(), $collect = array(), $str = '') {
$count = count($array);
foreach($array as $i => $val) {
if(is_array($val)) {
if(array_key_exists('element_rule_id' ,$val)) {
$collect[$val['element_rule_id']] = 1;
}
if(($count - 1) == $i) {
if(array_key_exists('0', $val['condition'])) {
deepIns($val['condition'], $collect);
}
else {
self::$result[] = $collect;
}
}
}
}
}
All is needed was $collection before deepIns($val['condition'], $collect);
$collection = deepIns($val['condition'], $collect);
hi i have following array
$langarr[0][0] = gb
$langarr[0][1] = 1
$langarr[1][0] = de
$langarr[1][1] = 2
$langarr[2][0] = fr
$langarr[2][1] = 3
$langarr[3][0] = it
$langarr[3][1] = 5
Now i wanna search to unset like
if(($keyy = array_search('de', $langarr[][0])) !== false) {
unset($langarr[$keyy]);
}
So i wanna search in the langarr[any][0] and if matched I want to delete the whole dataset like unset($langarr[X]);
How can this be achieved?
$langarr = array();
$langarr[0][0] = "gb";
$langarr[0][1] = "1";
$langarr[1][0] = "de";
$langarr[1][1] = "2";
$langarr[2][0] = "fr";
$langarr[2][1] = "3";
$langarr[3][0] = "it";
$langarr[3][1] = "5";
// Get the key of search array
$value = recursive_array_search("de",$langarr);
// print the key
print_r($value);
// unset the array "de" which has key "1"
unset($langarr[$value]);
// print the resultant array
print_r($langarr);
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
Use array_filter(). It takes a (anonymous) function as the second argument. The function itself receives an array element as its argument. If that function returns false, the array element is removed from the array.
So to take your example, if $needle is 'de', the subarray is removed.
$langarr = array(
array('gb', 1),
array('de', 2),
);
$needle = 'de';
$langarr = array_filter($langarr, function($row) use($needle) {
return ($row[0] != $needle);
});
Online test
<?php
$langarr[0][0] = "gb";
$langarr[0][1] = 1;
$langarr[1][0] = "de";
$langarr[1][1] = 2;
$langarr[2][0] = "fr";
$langarr[2][1] = 3;
$langarr[4][0] = "it";
$langarr[4][1] = 4;
print_r($langarr);
foreach($langarr as $key=>$data){
if($data[0]=='de'){
unset($langarr[$key]);
}
}
print_r($langarr);
?>