PHP: Format each table column with specific function - php

I want to print HTML table (30+ cols, 500+ rows) but before that I have to apply different function on almost each column values.
$sampleData = array(
0 => array(
'date' => '2015-10-20',
'time' => '12:30:00',
'price' => 500,
'currency' => 'EUR'
),
1 => array(
'date' => '2015-10-21',
'time' => '08:10:00',
'price' => 250,
'currency' => 'USD'
),
2 => array(
'date' => '2015-10-22',
'time' => '21:45:00',
'price' => 300,
'currency' => 'EUR'
)
);
So far I solved it with array of columns and names of functions that are called with call_user_func.
$cols = array(
'date' => 'self::formatDate',
'time' => 'self::formatTime'
);
And then create table like this:
$htmlRows = '';
foreach ($sampleData as $row) {
$htmlRows .= '<tr>';
foreach ($cols as $th => $function) {
$htmlRows .= '<td>'.call_user_func($cols[$th], $row[$th]).'</td>';
}
$htmlRows .= '</tr>';
}
To me it looked like quite elegant solution, but than I stuck on how to call function with two or more params, e.g. formatPrice($price, $currency); on third column while its values are stored under third and fourth key. Or is there a better way how to format table columns?
Thanks, sorry for english

Proposition:
Incorporate all fields you want to use for a specific column in a way you can split them easily, iterate over them and pass the collected values.
$cols = array(
'date' => 'self::formatDate',
'time' => 'self::formatTime',
'price,currency' => 'self::formatPrice',
);
and
$htmlRows = '';
foreach ($sampleData as $row) {
$htmlRows .= '<tr>';
foreach ($cols as $group => $function) {
$data = array();
$fields = explode(',', $group);
foreach ($fields as $field) {
$data[$field] = $row[$field];
}
$htmlRows .= '<td>'.call_user_func($cols[$th], $data).'</td>';
}
$htmlRows .= '</tr>';
}
You will have to adapt your formatXxx() functions to interpret the different representation.
It is actually a good idea to use the actual class name instead of self in the $cols array, because if you declare the functions as private and extend the class, the functions will not be found.

One way of doing it is to do another foreach and prepare a second array that is used for the HTML formatting.
foreach ($sampleData as $row) {
$newSampleData['date'] = self::formatDate($row['date']);
$newSampleData['something'] = self::formatDate($row['something'],'argument1','argument2');
... and so on
Then you use $newSampleData for your HTML code.

Related

PHP get the name of arrays in multidimensional array

I have a simple multidimensional array with two other arrays in it.
<?php
$data = array(
'first_array' => array(
'name' => 'Test1',
'description' => '...',
),
'second_array' => array(
'title' => 'Test2',
'description' => '...',
)
);
?>
And I have a simple foreach array like this:
function show($data, $id){
foreach ($data as $course) {
}
}
How can I display (and get) the name of the array in every iteration (I mean if it is 'first_array' or 'second_array', not the name fields in the arrays).
Use key=>val syntax
foreach ($data as $key=>$course) {
echo $key;
}
use this syntax for foreach :
foreach ($data as $name => $course) {
//do sth
}

rename Model Name from find('all') with cakePHP 2.X

I have a Model Order.
When I do find('all') in my table Order, cakephp return data like this:
array(
(int) 0 => array(
'Order' => array(
'id' => '10'
)
),
(int) 1 => array(
'Order' => array(
'id' => '11'
)
)
)
Is there any way for rename 'Order' into 'myTEST' ?
In your Order model you could possibly implement an afterFind callback to replace [Order] with [myTEST]. Something like this might work for you:
public function afterFind($results, $primary = false) {
$new_results = array();
foreach ($results as $key => $val) {
foreach($val as $v){
$new_results[$key]['myTEST'] = $v;
}
}
return $new_results;
// OR you could also take this approach - Less coding and perhaps more efficient
// foreach ($results as $key => $val){
// $results[$key]['myTEST'] = $results[$key]['Order'];
// unset($results[$key]['Order']);
// }
// return $results;
}
I have not tested this at all.

Chunk doesn't see arguments

I have this snippet (I want to get elements from .xml file):
$movies = simplexml_load_file('http://www.example.com/example.xml');
$out = "";
foreach ($movies as $movie) {
$properties = array(
'photo' => $movie->image,
'title' => $movie->title,
'desc' => $movie->teaser,
'channel' => $movie->channel,
'date' => $movie->date);
$out .= $modx->getChunk('tpl_movies-item', $properties);
}
return $out;
And chunk tpl_movies-item:
<article>
[[+photo]]
[[+title]]
[[+desc]]
[[+date]]
[[+channel]]
aaa
</article>
It shows only "aaa" (but when I add "echo $properties['photo']" it prints right value), when I change values in array to strings, eg. 'desc' => "lololololol" it works right. Could u help me what should I do?
The problem is probably in your foreach statement since simplexml_load_file() needs ->children() to loop through the different childs of the object at hand. Try:
foreach ($movies->children() as $movie) {
$properties = array(
'photo' => (string)$movie->image,
'title' => (string)$movie->title,
'desc' => (string)$movie->teaser,
'channel' => (string)$movie->channel,
'date' => (string)$movie->date);
$out .= $modx->getChunk('tpl_movies-item', $properties);
}
UPDATE
Try casting the properties as string as in the example above since they could be returned as objects.

Know the element level in multidimensional array

Well, I am here again dealing with arrays in php. I need your hand to guide me in the right direction. Suppose the following array:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
The - (hyphen) symbol only illustrates the deep level.
Well, I need to build another array (or whatever), because it should be printed as an HTML select as below:
-fruits
--green
---limon
---mango
--red
---apple
-cars
--ferrari
---enzo
----blue
----black
---318
--lamborg
---spider
---gallardo
----gallado-96
-----blue
-----red
-----gallado-98
Looks that for each level element, it should add a space, or hyphen to determinate that it belongs to a particular parent.
EDIT
The have provide an answer provideng my final code. The html select element will display each level as string (repeating the "-" at the begging of the text instead multi-level elements.
Here's a simple recursive function to build a select dropdown given an array. Unfortunately I'm not able to test it, but let me know if it works. Usage would be as follows:
function generateDropdown($array, $level = 1)
{
if ($level == 1)
{
$menu = '<select>';
}
foreach ($array as $a)
{
if (is_array($a))
{
$menu .= generateDropdown($a, $level+1);
}
else
{
$menu .= '<option>'.str_pad('',$level,'-').$a.'</option>'."\n";
}
}
if ($level == 1)
{
$menu = '</select>';
}
return $menu;
}
OK, I got it with the help of #jmgardhn2.
The data
This is my array:
$temp = array(
array(
'name' => 'fruits',
'sons' => array(
array(
'name' => 'green',
'sons' => array(
array(
'name' => 'mango'
),
array(
'name' => 'banana',
)
)
)
)
),
array(
'name' => 'cars',
'sons' => array(
array(
'name' => 'italy',
'sons' => array(
array(
'name' => 'ferrari',
'sons' => array(
array(
'name' => 'red'
),
array(
'name' => 'black'
),
)
),
array(
'name' => 'fiat',
)
)
),
array(
'name' => 'germany',
'sons' => array(
array(
'name' => 'bmw',
)
)
),
)
)
);
Recursive function
Now, the following function will provide an array with items like [level] => [name]:
function createSelect($tree, $items, $level)
{
foreach ($tree as $key)
{
if (is_array($key))
{
$items = createSelect($key, $items, $level + 1);
}
else
{
$items[] = array('level' => $level, 'text' => $key);
}
}
return $items;
}
Calling the funcion
Now, call the function as below:
$items = createSelect($temp, array(), 0);
Output
If you iterate the final $items array it will look like:
1fruits
2green
3mango
3banana
1cars
2italy
3ferrari
4red
4black
3fiat
2germany
3bmw

Check if an array of an array contains a certain string

I'm checking to make sure an array of arrays does not contain certain strings before adding any new child arrays to the parent array
I want to make sure that if an array with the same website and condition exists a new child array will not be added to the parent array.
e.g. in this example the $newArr must not be inserted in to the array $arr because their already exists an array with the same website and condition.
$arr = array(
array(
'website' => 'amazon',
'price' => 20,
'location' => 'uk',
'link' => '...',
'condition' => 'new'
),
array(
'website' => 'abe',
'price' => 20,
'location' => 'uk',
'link' => '...',
'condition' => 'new'
)
);
$newArr = array(
'website' => 'amazon',
'price' => 60,
'location' => 'uk',
'link' => '...',
'condition' => 'new'
)
I'm looking for an easy solution as using the function in_array on the parent array is not enough.
code so far
$arr = array();
foreach($table->find('tr.result') as $row){
if(($website = $row->find('a img',0))
&& ($price = $row->find('span.results-price a',0))
&& ($location = $row->find('.results-explanatory-text-Logo'))
&& ($link = $row->find('a',0))){
$website = str_replace( array('.gif','.jpg','.png'), '', basename($website->src));
$price = floatval(trim(str_replace(',', '', $price->innertext), "£"));
$location = "uk";
$link = $link->href;
$arr[] = array(
'website' => $website,
'price' => $price,
'location' => $location,
'link' => $link,
'condition' => 'new'
);
}
}
You loop over $arr each time to look for $website and $condition (always 'new'?) or you can keep a secondary array of the found keys. If you're starting with an empty $arr each time, the second approach will work and be faster.
$arr = array();
$keys = array();
foreach($table->find('tr.result') as $row){
if(...){
...
$condition = 'new'; // set as needed
// track seen keys
$key = $website . '|' . $condition; // assumes neither field contains '|'
if (!isset($keys[$key])) {
$keys[$key] = true;
$arr[] = array(...);
}
}
}
I hope the comments in the below code speak for themselves... I'm not a PHP pro, and this is probably not the most elegant way, but I believe the logic makes sense. Obviously the $new_array object has some variables that aren't declared but it's for example only.
I hope that helps and that no one down votes me :)
<?php
// Original array
$arr = array();
foreach($result as $row) {
// Get the new array as an object first so we can check whether to add to the loop
$new_array = array(
'website' => $website,
'price' => $price,
'location' => $location,
'link' => $link,
'condition' => 'new'
);
// If the original array is empty there's no point in looping through it
if(!empty($arr)) {
foreach($arr as $child) {
// Check through each item of the original array
foreach($new_array as $compare) {
// Compare each item in the new array against the original array
if(in_array($compare, $child)) {
// if there's a match, the new array will not get added
continue;
}
}
}
}
// If there's no match, the new array gets added
$arr[] = $new_array;
}
?>

Categories