CodeIgniter - foreach loop - php

TL;DR
I'm trying to loop all the rows and output it with html. When I'm looping it, I get an array with the properties and values of a single row which is also the last row, when I do not loop it, I get 2 arrays (each array is a row) within an array. For some reason it doesn't loop it and display all the rows as it should, how do I fix this?
I'm trying to make a loop of sections and the articles within them, where as each article has a parent section.
In the database, there are 5 sections and 2 articles, article #1 has section #1 as it's parent and article #2 has section #2 as it's parent.
When print it as an array without looping it, I get the following array;
Array
(
[0] => Array
(
[s_id] => 1
[s_name] => News
[s_slug] => news
[s_visibility] => 1
[s_type] => 1
[s_status] => 1
[s_permission] => 0
[s_external] => 0
[s_location] => news
[s_color] => 1
[s_homepage] => 1
[a_id] => 1
[a_section] => 1
[a_title] => Ted Cruz’s ‘Secret’ Skill That No President Has Likely Had Since Thomas Jefferson
[a_description] => Apparently Cruz, whose famed 2013 marathon filibuster speech over defunding Obamacare jumped across a range of topics, has an uncanny capability to remember things he hears verbatim.
[a_content] => Apparently Cruz, whose famed 2013 marathon filibuster speech over defunding Obamacare jumped across a range of topics, has an uncanny capability to remember things he hears verbatim.
[a_views] => 0
[a_visibility] => 1
[a_date] => 17.11.2015
[a_author] => 1632422528
[a_category] => 1
[a_slug] =>
)
[1] => Array
(
[s_id] => 2
[s_name] => VOD
[s_slug] => vod
[s_visibility] => 1
[s_type] => 2
[s_status] => 1
[s_permission] => 0
[s_external] => 0
[s_location] => vod
[s_color] => 2
[s_homepage] => 1
[a_id] => 2
[a_section] => 2
[a_title] => GTA V PC Edition Released
[a_description] => Wondering where the score is? Our GTA Online review will remain scoreless, as a score does not properly reflect its continuously changing nature. Here's how and why we decided to do it this way.
[a_content] => Wondering where the score is? Our GTA Online review will remain scoreless, as a score does not properly reflect its continuously changing nature. Here's how and why we decided to do it this way.
[a_views] => 0
[a_visibility] => 1
[a_date] => 19.11.2015
[a_author] => 1632422528
[a_category] => 1
[a_slug] =>
)
)
But when I run it into a foreach loop, it outputs only a single array which is the later one (1).
I'm using CodeIgniter 3, the loop is inside a library called "Global_functions",
The model is "Functions_model".
Global_functions (only the related function, not the entire class because it contains other unrelated functions):
public function get_homepage_sections()
{
$getHomeData = $this->CI->functions_model->get_homepage_data();
foreach ($getHomeData as $get_sections)
{
switch ($get_sections['s_color'])
{
case 1:
$sectionColor = "blue";
break;
case 2:
$sectionColor = "purple";
break;
case 3:
$sectionColor = "orange";
break;
case 4:
$sectionColor = "green";
break;
default:
$sectionColor = "";
break;
}
$outputData = '
<li>
<div><h2 class="category ' . $sectionColor . '">' . $get_sections['s_name'] . '</h2></div>';
$outputData .= '
</li>';
}
return $get_sections;
}
Functions_model;
public function get_homepage_data()
{
$selected_columns = array(
'sections.s_id',
'sections.s_name',
'sections.s_slug',
'sections.s_visibility',
'sections.s_type',
'sections.s_status',
'sections.s_permission',
'sections.s_external',
'sections.s_location',
'sections.s_color',
'sections.s_homepage',
'articles.a_id',
'articles.a_section',
'articles.a_title',
'articles.a_description',
'articles.a_content',
'articles.a_views',
'articles.a_visibility',
'articles.a_date',
'articles.a_author',
'articles.a_category',
'articles.a_slug'
);
$query = $this->db->select( $selected_columns )
->from( config_item('sections') . ', ' . config_item('articles') )
//->join( config_item('articles'), 'articles.a_section = sections.s_id' )
->where( 'articles.a_section = sections.s_id' )
//->or_where( 'user_email', $user_string )
->get();
if ( $query->num_rows() >= 1 )
{
return $query->result_array();
}
}
Being called from the controller as follows (homepageSection);
public function index()
{
/* if ($this->require_role('admin')) {
echo $this->load->view('examples/page_header', '', TRUE);
echo '<p>You are logged in!</p>';
echo $this->load->view('examples/page_footer', '', TRUE);
}*/
// return $isAutoRememberMe;
//extra_for_auth();
// Call a function of the model
$data['getGlobalMessage'] = $this->global_functions->get_global_message();
$data['userOptions'] = $this->global_functions->extra_for_auth();
$data['homepageSection'] = $this->global_functions->get_homepage_sections();
//print_r ($data);
$this->parser->parse('template/header', $data);
$this->parser->parse('sections/homepage', $data);
$this->load->view('template/footer');
}
section/homepage file contains the call {homepageSection}, as you can see the parser is called and parses the file rather than loading it with view().

I think there is an error in get_home_sections()
instead of:
return $get_sections;
you should:
return $getHomeData
you are returning the last item from the array, that looks like the problem you stated.
Another point i see a little bit confusing is the var you are cummulating html.
$outputData is being reset in each loop, and you are not doing nothing with it. It's a good idea to initialize it at the begining of the funcion as empty string
$outputData = '';
and in the loop you should do an additive assingment with .=

Related

pass correct multidimensional array values to function (without duplicates)

I am trying to get away from doing things manually and repetitively by correctly utilizing loops and functions (methods) in oop programming; but I have hit a major stumbling block as it regards to multidimensional array groups, in passing the correct values to the necessary abstracted function (method) responsible for a database action.
Any help at all is very much welcomed and will enable me to move on from this stumbling block that I have been trying to push away for days upon days but without progress and it is out of true frustration and much agony that I am here begging for help.
Below is the code that for simplicity I have shortened as much as possible (can be easily tested locally by copying and pasting):
// array with table properties and form values - start
$form_fields_arr = [
'group' => [
'anime' => [ // genre
'table_prop' => [ // for update query - table properties
'table_name' => 'anime_tbl',
'account_id' => 2,
'visible' => 'yes'
],
'form_data' => [ // for update query - form values
'2' => 'Attack on Titan',
'4' => 'RWBY',
'6' => 'Rurouni Kenshin',
'8' => 'A Silent Voice'
]
],
'movie' => [ // genre
'table_prop' => [ // for update query - table properties
'table_name' => 'movie_tbl',
'account_id' => 4,
'visible' => 'yes'
],
'form_data' => [ // for update query - form values
'1' => 'Queen of Katwe',
'3' => 'Forest Gump',
'5' => 'War Horse',
'7' => 'The Fault in our Stars'
]
]
]
]; // ... end
// loop through multidimensional array and pass values to function - start
foreach ($form_fields_arr['group'] as $frm_key_1 => $frm_val_1) { // 2d array
foreach ($frm_val_1 as $frm_key_2 => $frm_val_2) { // 1d array
if (strcasecmp($frm_key_1, $frm_key_1) === 0) { // group by genre
foreach ($frm_val_2 as $frm_key_3 => $frm_val_3) { // 1d array
if (strcasecmp($frm_key_2, 'form_data') === 0) {
$title = $form_fields_arr['group'][$frm_key_1]['form_data'][$frm_key_3]; // anime/movie title
}
if (isset($frm_val_2['table_name']) &&
isset($frm_val_2['account_id']) &&
isset($frm_val_2['visible']) &&
isset($title)
) {
dbUpdate(
$frm_val_2['table_name'],
$frm_val_2['account_id'],
$frm_val_2['visible'],
$title
);
}
} // 1d array
} // if block
} // 1d array
} // 2d array
// ... end
// function that receives passed values - start
function dbUpdate($table_name, $account_id, $title_col, $form_value) {
$test_val_arr = [$table_name, $account_id, $title_col, $form_value];
return print_r($test_val_arr);
} // ... end
The above code outputs:
// array values passed to and returned from function
Array (
[0] = movie_tbl
[1] = 4
[2] = yes
[3] = A Silent Voice
)
Array (
[0] = movie_tbl
[1] = 4
[2] = yes
[3] = A Silent Voice
)
Array (
[0] = movie_tbl
[1] = 4
[2] = yes
[3] = A Silent Voice
)
Array (
[0] = movie_tbl
[1] = 4
[2] = yes
[3] = A Silent Voice
)
But the desired result that I am trying to achieve is:
// for anime genre - array values passed to and returned from function
Array (
[0] = anime_tbl
[1] = 2
[2] = yes
[3] = Attack on Titan
)
Array (
[0] = anime_tbl
[1] = 2
[2] = yes
[3] = RWBY
)
Array (
[0] = anime_tbl
[1] = 2
[2] = yes
[3] = Rurouni Kenshin
)
Array (
[0] = anime_tbl
[1] = 2
[2] = yes
[3] = A Silent Voice
)
// for movie genre - array values passed to and returned from function
Array (
[0] = movies_tbl
[1] = 4
[2] = yes
[3] = Queen of Katwe
)
Array (
[0] = movies_tbl
[1] = 4
[2] = yes
[3] = Forest Gump
)
Array (
[0] = movies_tbl
[1] = 4
[2] = yes
[3] = War Horse
)
Array (
[0] = movies_tbl
[1] = 4
[2] = yes
[3] = The Fault in our Stars
)
so upon everything royally failing with me spending literally about a week trying to fix this, telling myself that it is very simple and I really shouldn't be stuck here, out of desperation I decided to go back to my repetitive ways and tried the following:
// new array without table properties - start
$new_array = [];
$new_array['group']['anime'] = $form_fields_arr['group']['anime']['form_data'];
$new_array['group']['movie'] = $form_fields_arr['group']['movie']['form_data']; // ... end
// loop through multidimensional array and pass values to function - start
foreach ($new_array['group'] as $key_1 => $val_1) { // 2d array
foreach ($val_1 as $key_2 => $val_2) { // 1d array
if (strcasecmp($key_1, $key_1) === 0) {
dbUpdate('anime_tbl', 2, 'yes', $val_2);
dbUpdate('movie_tbl', 4, 'yes', $val_2);
} // if block
} // 1d array
} // 2d array
// ... end
But the results are still very much undesirable. Everything was working fine until I started using multidimensional arrays, simply because I realized that utilizing multidimensional arrays help me to shorten my code in other areas considerably. But I am stuck here and will have to go back further up and undo quite a lot of changes if I can't get this to work. I am pleading for help from any good soul out there. Please help me someone! Anyone!
I am being optimistic here and assuming that if by any chance I do get some help in fixing the above problem, could someone please also teach me how to loop through an array structure like the one below while yet getting the desired results without duplicates (I have truly tried but have truly failed):
// array with table properties and form values - start
$form_fields_arr = [
'table_prop' => [ // table properties group
'anime' => [ // for update query - table properties
'table_name' => 'anime_tbl',
'account_id' => 2,
'visible' => 'yes'
],
'movie' => [ // for update query - table properties
'table_name' => 'movie_tbl',
'account_id' => 4,
'visible' => 'yes'
]
],
'form_data' => [ // for update query - form values
'anime' => [ // genre
'2' => 'Attack on Titan',
'4' => 'RWBY',
'6' => 'Rurouni Kenshin',
'8' => 'A Silent Voice'
],
'movie' => [ // genre
'1' => 'Queen of Katwe',
'3' => 'Forest Gump',
'5' => 'War Horse',
'7' => 'The Fault in our Stars'
]
]
]; // ... end
You got a logic mistake in your for loops. First of all your variable namings are not very intuitive. $frm_key_1, $frm_key_2, etc. look alike and force the reader to have the array structure in mind all the time to understand the variables meaning. This led to a mistake like this one: if( strcasecmp($frm_key_1, $frm_key_1) === 0 ). This is always true.
Then you had two exclusive conditions:
if (strcasecmp($frm_key_2, 'form_data') === 0)
And:
if (isset($frm_val_2['table_name']) && /* ... */) {
If $frm_key_2 is 'form_data' you are in the second child of the genre array, yet the fields 'table_name', etc. are defined only in the first one (witht the key 'table_prop'). So both conditions can never be true at the same time.
Your condition to trigger the dbUpdate() function was, that all fields of the 'table_prop' array were present (which you iterated through at the same time), and a $title was set aswell. This was only true after your third for-loop iterated for the second time. During that iterations the $title variable got overwritten constantly, but no sbUpdate() was triggered, because $frm_val_2 had the values from 'form_data' instead of 'table_prop'. So after the 3rd for loop finished the 2nd time $title was 'A Silent Voice', which is simply the last child of the first 'form_data' array. Afterwards your 2nd for loop iterated the 2nd 'table_prop' array again, which means that now the 'dbUpdate()' condition was true, so it postet 4 times (number of childs in the 'table_prop' array) the parameters with $title = 'A Silent Voice'.
You tried to make everything as generic as possible, making everything over complicated. The best solution that works here is one that respects the specific structure.
This works:
<?php
// array with table properties and form values - start
$form_fields_arr = [
'group' => [
'anime' => [ // genre
'table_prop' => [ // for update query - table properties
'table_name' => 'anime_tbl',
'account_id' => 2,
'visible' => 'yes'
],
'form_data' => [ // for update query - form values
'2' => 'Attack on Titan',
'4' => 'RWBY',
'6' => 'Rurouni Kenshin',
'8' => 'A Silent Voice'
]
],
'movie' => [ // genre
'table_prop' => [ // for update query - table properties
'table_name' => 'movie_tbl',
'account_id' => 4,
'visible' => 'yes'
],
'form_data' => [ // for update query - form values
'1' => 'Queen of Katwe',
'3' => 'Forest Gump',
'5' => 'War Horse',
'7' => 'The Fault in our Stars'
]
]
]
];
// loop through multidimensional array and pass values to function - start
foreach ($form_fields_arr['group'] as $genreData) {
$tableProperties = $genreData['table_prop'];
if (!isset($tableProperties['table_name'])
|| !isset($tableProperties['account_id'])
|| !isset($tableProperties['visible'])) {
continue;
}
$data = $genreData['form_data'];
foreach ($data as $title) {
dbUpdate(
$tableProperties['table_name'],
$tableProperties['account_id'],
$tableProperties['visible'],
$title
);
}
}
// function that receives passed values - start
function dbUpdate($table_name, $account_id, $title_col, $form_value) {
$test_val_arr = [$table_name, $account_id, $title_col, $form_value];
return print_r($test_val_arr);
} // ... end
For the last part of the question that wasn't answered, thanks to Philipp Maurer's answer, after playing around with the code I got it to work. I am just placing the answer here for anyone who might have a similar problem and would like to better understand how to group and fetch values from a multidimensional array using a foreach loop without duplicates or incorrect results. See below code:
// array with table properties and form values - start
$form_fields_arr = [
'table_prop' => [ // table properties group
'anime' => [ // for update query - table properties
'table_name' => 'anime_tbl',
'account_id' => 2,
'visible' => 'yes'
],
'movie' => [ // for update query - table properties
'table_name' => 'movie_tbl',
'account_id' => 4,
'visible' => 'yes'
]
],
'form_data' => [ // for update query - form values
'anime' => [ // genre
'2' => 'Attack on Titan',
'4' => 'RWBY',
'6' => 'Rurouni Kenshin',
'8' => 'A Silent Voice'
],
'movie' => [ // genre
'1' => 'Queen of Katwe',
'3' => 'Forest Gump',
'5' => 'War Horse',
'7' => 'The Fault in our Stars'
]
]
]; // ... end
// loop through multidimensional array and pass values to function - start
foreach ($form_fields_arr as $index => $group_array) {
foreach ($group_array as $genre_key => $genre_val) {
if (!isset($group_array[$genre_key]['table_name']) ||
!isset($group_array[$genre_key]['account_id']) ||
!isset($group_array[$genre_key]['visible'])
) {
continue;
}
foreach ($form_fields_arr['form_data'][$genre_key] as $data_key => $data_title) {
dbUpdate(
$group_array[$genre_key]['table_name'],
$group_array[$genre_key]['account_id'],
$group_array[$genre_key]['visible'],
$data_title
);
}
}
}
// ... end
// function that receives passed values - start
function dbUpdate($table_name, $account_id, $title_col, $form_value) {
$test_val_arr = [$table_name, $account_id, $title_col, $form_value];
return print_r($test_val_arr);
} // ... end

Converting PHP array manipulation to Ruby hashes

I've written this script to be run in PHP, and am trying to convert it to Ruby.
Code:
$cases = array();
foreach($results as $result)
{
if(!array_key_exists($result['id'], $cases))
$cases[$result['id']] = array($result);
else
$cases[$result['id']][] = $result;
}
foreach($cases as $key => $case)
{
foreach($case as $payment)
{
if(count($case) > 1)
{
$cases[$key]['total'] += ($payment['p1'] > $payment['p2']) ? $payment['p1'] : $payment['p2'];
} else {
$cases[$key]['total'] = ($payment['p1'] > $payment['p2']) ? $payment['p1'] : $payment['p2'];
}
}
}
In Ruby, I have the results as an array returned by MySQL (using mysql2 gem). Using the loop below, it prints every row. How can I check if the key exists when it does not provide keys?
What's the best way to implement this code in Ruby? How can I add a hash onto a hash in Ruby similar to adding an array onto an array in PHP.
results.each(:as => :array) do |row|
puts row.inspect
end
More explanation:
PHP Structure
Array(
0 => Array(
Array(
[id] => 'random id',
[p1] => 534,
[p2] => 105
),
Array(
[id] => 'random id',
[p1] => 335,
[p2] => 425
)
),
1 => Array(
Array(
[id] => 'random id',
[p1] => 259,
[p2] => 124
)
)
)
And i'm trying to iterate over each array inside the first, and if p1 > p2, add p1 to the total key on that array. i.e., the 0 index would look like this:
0 => Array(
'total' => 959,
Array(
[id] => 'random id',
[p1] => 534,
[p2] => 105
),
Array(
[id] => 'random id',
[p1] => 335,
[p2] => 425
)
)
Are you trying to group by result['id']? I believe that "translating" your PHP code to ruby will look something like this:
cases = {}
results.each do |result|
if cases[result['id']]
cases[result['id']] << result
else
cases[result['id']] = [result]
end
end
Another way to get the same result is to use group_by:
cases = results.group_by { |result| result['id'] }
The second part "translated" to ruby will look something like this:
cases.each do |key, c|
c.each do |payment|
if c.count > 1
c['total'] += (payment['p1'] > payment['p2']) ? payment['p1'] : payment['p2']
else
c['total'] = (payment['p1'] > payment['p2']) ? payment['p1'] : payment['p2']
end
end
end
(this will actually not work in ruby, since an array cannot have an arbitrary key like 'total' - it accepts only numbers in its brackets. You will have to modify this code to hold the totals in a different structure)
Again, a more idiomatic way of summing up the max between 'p1' and 'p2' of each payment in each case might look more like this:
totals = cases.values.map do |c|
c.inject(0) { |sum, payment| sum + [payment['p1'], payment['p2']].max }
end

php recursive function to built menu

i m trying to build recursive menu using PHP but not succeeding
mysql table
menuid name parentid
and my php code
function generateMenubar()
{
$data = Yii::app()->db->createCommand("select * from menu");
$result = $data->queryAll();
$html = '<ul class = "navigation">';
foreach($result as $row)
{
if($row['parentid'] == "0")
{
$html .= '<li><span>'.$row["menuname"].'</span>';
$menu_id = $row['menuid'];
$html .= $this->generateHTML($result,$menu_id,$html);
}
}
return $html;
}
function generateHTML($result,$menu_id,$html)
{
foreach($result as $row_sub)
{
if($menu_id == $row_sub['parentid'])
{
$html .= '<ul><li><span>'.$row_sub['menuname'].'</span>';
$menu_id = $row_sub['menuid'];
$html .= $this->generateHTML($result,$menu_id,$html);
$html .= '</li>';
}
}
return $html.'</ui>';
}
but this loop is not stopping and generating wrong output. it can have sub levels upto n level. i want to make it dynamic cuz levels may change in future any suggestion ?
Your problem is that you do not have a structured result to iterate over. You might have SubElement 2 > 3 > 4 as your first result but 2 > 3 > 1 as your 5th Result. So you can't just iterate over the result once and build your html.
What you want to do (appart from, switching to nested sets, which is what you REALLY want to do wink) is structure your result first.
Iterate over your result and build a nested array to iterate over recusively to build your HTML. To find "where to put your element" in your recursive array you need to recursively check back with your existing array always as well. IF all you store is id and parent id, how to find out what the root element is before you checked ALL elements right?
So i could write the code to do so, but i rather do not because it would be a horrible solution anyway.
To do so more efficiently it would really help if you do not only store your parentid but a level as well.
Then you could store your elements in a two dimensional array storing all elements for each level and then recursively use that array. i.e.
$navigationTempArray = array();
foreach($fakeMySQLResult as $row)
{
if(!array_key_exists($row['level'], $navigationTempArray )) {
$navigationTempArray[$row['level']] = array();
}
if(!array_key_exists($row['parentid'], $navigationTempArray[$row['level']] )) {
$navigationTempArray[$row['level']][$row['parentid']] = array();
}
$navigationTempArray[$row['level']][$row['parentid']][] = $row;
}
now you have an array like this:
array (
0 => array(
'root' => array(
1 => array('title' => 'Start' ...)
2 => array('title' => 'Team' ...)
3 => array('title' => 'Projects' ...)
)
),
1 => array(
2 => array(
4 => array('title' => 'Development' ...)
5 => array('title' => 'Design' ...)
6 => array('title' => 'Sales' ...)
),
3 => array(
7 => array('title' => 'Mayhem' ...)
8 => array('title' => 'X' ...)
)
),
2 => array(
4 => array(
9 => array('title' => 'PHP' ...)
10 => array('title' => 'MySQL' ...)
)
)
)
Now you can iterate over this array recursively, solving every level for every item to infinity ;-)
function returnSubNavigation($id,$level,$fullNavigationArray) {
$html = '';
if(array_key_exists($level, $fullNavigationArray) && array_key_exists($id, $fullNavigationArray[$level])) {
$html .= '<ul>';
foreach($fullNavigationArray[$level][$id] as $subElement) {
$html .= '<li><span>'.$subElement["menuname"].'</span>';
$html .= returnSubNavigation($subElement['id'], $level+1, $fullNavigationArray);
$html .= '</li>';
}
$html .= '</ul>';
}
return $html;
}
echo returnSubNavigation('root', 0, $navigationTempArray);
Here is an online fiddle kind of thing that proves it works
Some people who do not want to use nested sets often store pathes rather than parent id's.
i.e.:
| id | path |
| 1 | 1 |
| 2 | 2 |
| 3 | 1.1 |
| 4 | 1.2 |
| 5 | 2.1 |
| 6 | 3 |
This is a lot easier (cheaper in terms of performance) to iterate over. You can sort it a lot easier. Still, it brings a lot of problems and restrictions.

How can I manipulate my array, so if there is a scan within 60min with the same

This is really hard to explain, but i will do my best.
I have a array called arrayoftransationcs which contains 4 strings. *SCAN, MEMBER_ID, RESTAURANT, TIME, PAID. If a scan is paid, it will defined as 1, and if not it will have 0.
So the main question to my problem is, how can I get scan that contain paid = 0 which has not have paid = 1 within 60 min. I will give an example.
Example A In this example, there is 3 scan which comes from the same cafe x within 20 min. The first 2 has been defined as paid = 0, and the last has been defined as paid = 1. Because there is paid = 1 within 60min with the same member_id and restaurant, i dont want any of the scan
Scan A 1635752 Cafe X 17-11-2013 21:00 Paid 1
Scan B 1635752 Cafe X 17-11-2013 20:50 Paid 0
Scan C 1635752 Cafe X 17-11-2013 20:40 Paid 0
Example B In this example, there is also 3 scan from the same member, same restaurant, within 60min, but all of them has been defined as paid = 0. Because there is no paid = 1 in this example, i want these in a array. This is the goal. But there is a twist here, because there is more than 1 scan to use, i only want the latest scan in this example, which will mean only scan A can be used
Scan A 1635752 Cafe X 17-11-2013 21:00 Paid 0
Scan B 1635752 Cafe X 17-11-2013 20:50 Paid 0
Scan C 1635752 Cafe X 17-11-2013 20:40 Paid 0
So I hope you understand the my question. I need paid = 0 scan if there is not a paid = 1 scan subsequently with the same member_id, restaurant within 60min
This is how i tried.
I am looping my array 2 times, and then checking for it the same member_id (cardid) and restaurants are equals together, if yes, then check time. If it is whitin 60min, mark the scan as double
foreach($arrayoftransationcs as $key => $array)
{
$time=$arrayoftransationcs[$key]['created'];
$cardid = $arrayoftransationcs[$key]['cardid'];
$restaurant_id = $arrayoftransationcs[$key]['restaurant_id'];
if(isset($arrayoftransationcs[$key]))
{
foreach($arrayoftransationcs as $k1=>$v1)
{
$time2=$arrayoftransationcs[$k1]['created'];
if($key<$k1)
{
if($arrayoftransationcs[$k1]['cardid']==$cardid && $arrayoftransationcs[$k1]['restaurant_id']==$restaurant_id)
{
if(compare($time,$time2))
{
$arrayoftransationcs[$key]['error'] = 'double';
$arrayoftransationcs[$k1]['error'] = 'double';
}
}
}
}
}
}
checking the time here.
function compare($firsttime, $secondtime)
{
$interval = $firsttime-$secondtime;
$dif=round(abs($interval) / 60);
if ($dif < 60 || $dif < -60 )
{
if ($dif!==0)
{
return true;
}
else
{
return false;
}
}
}
This is the place, where i filter after paid = 0 and does not contain anything in the error field.
foreach ($arrayoftransationcs as $key)
{
if($key['paid'] == 0 && empty($key['error']))
{
$ids[] = $key['transactionid'];
}
}
But I am not sure it is the right approach, I did it with the code. For technically, I select all scan which has the same membership number, restaurant with "double" in the field error, if it is paid = 1 or 0, does not matter .. this is not right, i think.
So I'm missing something here, checking if there is paid = 0 scan here if yes, check if there is a paid = 1 scan within the next 60min having the same medlem_id and restaurant. If so, then mark them as doubles.
This is how you do it:
<?php
// Data Source
$arrayoftransationcs = array(
array(
'transactionid' => 16148,
'cardid' => 10010234,
'created' => 1380650784,
'restaurant_id' => 32089,
'paid' => 1
),
array(
'transactionid' => 16552,
'cardid' => 10010241,
'created' => 1381522288,
'restaurant_id' => 41149,
'paid' => 1
),
array(
'transactionid' => 16936,
'cardid' => 10010440,
'created' => 1386247655,
'restaurant_id' => 47897,
'paid' => 0
),
array(
'transactionid' => 16808,
'cardid' => 10010557,
'created' => 1382361447,
'restaurant_id' => 43175,
'paid' => 0
),
array(
'transactionid' => 18932,
'cardid' => 10010440,
'created' => 1386247655,
'restaurant_id' => 47897,
'paid' => 1
)
);
// Helper Function
function getUnpaidWithinHour($transactions) {
$unpaid_transactions = array();
$time_now = time();
foreach ($transactions as $transaction) {
if ($transaction['paid']) continue;
if (($time_now - $transaction['created']) < 3600 && !$transaction['paid']) {
$unpaid_transactions[] = $transaction;
}
}
return $unpaid_transactions;
}
// Test
$unpaid_transactions = getUnpaidWithinHour($arrayoftransationcs);
echo "<pre>";
print_r($unpaid_transactions);
echo "<pre>";
?>
Outputs:
Array
(
[0] => Array
(
[transactionid] => 16936
[cardid] => 10010440
[created] => 1386247655
[restaurant_id] => 47897
[paid] => 0
)
)
To test if this is working, I edited the transaction 16936 to have a timestamp of 5 minutes ago and ran the function. The code correctly detected that transaction.
Try it yourself and with your own datasource.
Let's make things simple, your question is: Find paid = 0 scan if there is not paid = 1 with same member_id within 60min, since lack of test data, so i'll describe below with nature language in php style:
make an empty arrayPaid
foreach (all data) {
if time passed greater than 60min, continue;
if paid
add member_id in arrayPaid: arrayPaid[member_id] = something
continue;
if unpaid and arrayPaid[member_id] is not set
this is the data you want
}
The logic is clear, easy to write your real code. And one important thing is, your data need to be order by time in desc.
I found the answer by doing this.
foreach ($results->result_array() as $filterofresults)
{
if($filterofresults['paid'] == 1)
{
$arrayoftransationcs1[]=$filterofresults;
}
if($filterofresults['paid'] == 0)
{
$arrayoftransationcs[]=$filterofresults;
}
}
foreach($arrayoftransationcs as $key => $array)
{
$time=$arrayoftransationcs[$key]['created'];
$cardid = $arrayoftransationcs[$key]['cardid'];
$restaurant_id = $arrayoftransationcs[$key]['restaurant_id'];
if(isset($arrayoftransationcs[$key]))
{
foreach($arrayoftransationcs1 as $k1=>$v1)
{
$time2=$arrayoftransationcs1[$k1]['created'];
if($key<$k1)
{
if($arrayoftransationcs1[$k1]['cardid']==$cardid && $arrayoftransationcs1[$k1]['restaurant_id']==$restaurant_id)
{
if(compare($time,$time2))
{
$arrayoftransationcs[$key]['error'] = 'Dobbelt';
$arrayoftransationcs1[$k1]['error'] = 'Dobbelt';
}
}
}
}
}
}
foreach ($arrayoftransationcs as $key)
{
if($key['paid'] == 0 && empty($key['error']))
{
$samlet[] = get_all_data($key['transactionid']);
}
}

banner rotator advertising with probability

I have banners advertising with number of views, like CPM system.
And for example :
i have 3 banner:
banner1 with 20.000 nr of views
banner2 with 10.000 nr of views
banner3 with 5.000 nr of views
and on my website the banner must to appear in this position (when the page is reloaded) :
banner1 banner2 banner1 banner2 banner3
if the number of views is higher then the probability of apparition is higher
how can i do this in php?
First of all, your system is just... stupid. It perpetuates banners with lots of views while newly created banners with 0 or few views will never get a chance to be picked and thus will never be actually seen...
That being said, if you have an array that looks like this:
$banners = array
(
'banner1' => 1,
'banner2' => 2,
'banner3' => 4,
'banner4' => 8,
'banner5' => 16,
);
You can use a function like this one to weightily pick one banner:
function Probability($data)
{
if (is_array($data) === true) {
$result = 0;
$probability = mt_rand(1, array_sum($data));
foreach ($data as $key => $value) {
$result += $value;
if ($result >= $probability) {
return $key;
}
}
}
return false;
}
Usage (test it # CodePad.org or # IDEOne):
echo Probability($banners); // banner5
Sample from 100 executions:
Array
(
[banner5] => 41
[banner4] => 38
[banner3] => 10
[banner2] => 8
[banner1] => 3
)
Here's a php way to do it
I'm imagining your array will look something like this...
$banners = array(
array (
'name' => 'banner1',
'views' => 20
),
array (
'name' => 'banner2',
'views' => 10
),
array (
'name' => 'banner3',
'views' => 5
)
);
This function basically loops through the banners and however many views a banner has, that many items of its array index are added to an array. Then a random one is chosen. Items with more views have a better chance of being chosen.
function getWeightedRandom( $array ) {
$universe_array = array();
foreach ( $array as $k => $b ) {
$universe += $b['views'];
$universe_array = array_pad( $universe_array, $universe, $k );
}
$rand = mt_rand( 0, count( $universe_array ) -1 );
return $array[ $universe_array[ $rand ] ];
}
$r = getWeightedRandom($banners);
print_r($r);
A simple mysql option is:
select * from banners order by rand() * views desc limit 1
banners with more views will have a higher chance of being the top result

Categories