Walk through a table to grab unique certificate numbers for shares - php

The table I am working with is named shares. Assuming $share is an instance of the model Share. A share belongs to a company.
| id | company_id | number_of_shares |
| 31 | 1 | 3 |
| 33 | 1 | 9 |
| 34 | 1 | 4 |
I want to call $share->getCertificate() and have it return a certificate number, these should be:
id 31 -> 1
id 33 -> 2
id 34 -> 3
Note: this increments a unique certificate number based on its location in the table.
Then when I call $share->getDistinctive() I wish to have it return the following:
id 31 -> array('start' => 1, 'end' => 3)
id 33 -> array('start' => 4, 'end' => 13)
id 34 -> array('start' => 14, 'end' => 18)
Note: this increments based on the number of shares starting at 1
Assumptions
Table will always be ordered by id
I am using laravel 4.0.
Happy for someone to recommend a better title so that other people can find the the solution to their problem.

Worked it out - not sure why I thought it would've been more complicated.
getCertificateNumber()
public function getCertificateNumber()
{
$x=1;
foreach($this->company->holdings()->get() as $holding)
{
if($holding->id == $this->id)
{
return $x;
}
$x++;
}
}
getDistinctiveNumbers()
public function getDistinctiveNumbers()
{
$shares=0;
foreach($this->company->holdings()->orderBy('id')->get() as $holding)
{
if($holding->id == $this->id)
{
return ['start'=> $shares + 1, 'end' => $shares + $this->number_shares];
}
$shares += $holding->number_shares;
}
}

Related

converting a related database table object into a nested array - PHP

i have some dummy related data in my table "you can take a look at it bellow". i want to nest the data according to their relationships into one array.
Table Data:
+-----+------+--------+
| uid | name | parent |
+-----+------+--------+
| 1 | A | 0 |
| 2 | B | 1 |
| 3 | C | 1 |
| 4 | D | 2 |
| 5 | E | 3 |
| 7 | G | 3 |
| 9 | H | 4 |
| 10 | I | 4 |
| 11 | J | 7 |
+-----+------+--------+
the array is going to be like array('A' =>array('B'=>'D','C'=>array(...)).
am currently using codeigniter and here is what i've done
CODE
public function nestDataIntoArray($id)
{
$this->db->where('uid', $id);
$query = $this->db->get('binary_tbl');
$result = [];
if ($query->num_rows() > 0) {
foreach ($query->result() as $k) {
// secondLevel deep
$secondLevel = $this->getSubLevel($k->uid);
$secondLevelRowCount = $secondLevel->num_rows();
if ($secondLevelRowCount > 0 ) {
if ($secondLevelRowCount > 1) {
foreach ($secondLevel->result() as $key) {
// create second level deep array
$result[$k->name][$key->name][] = $this->getSubLevel($key->uid)->row('name');
// thirdLevel deep
$thirdLevel = $this->getSubLevel($key->uid);
$thirdLevelRowCount = $thirdLevel->num_rows();
if ($thirdLevelRowCount > 0) {
if($thirdLevelRowCount > 1){
foreach ($thirdLevel->result() as $tKey) {
// create third level deep array
$result[$k->name][$key->name][$tKey->name] = $this->getSubLevel($tKey->uid)->row('name');
}
}else{
foreach ($thirdLevel->result() as $tKey) {
$result[$k->name][$key->name][$tKey->name] = $this->getSubLevel($tKey->uid)->row('name');
}
}
} else {
$result[$k->name][$key->name] = $this->getSubLevel($key->uid)->result_array();
} //end thirdLevel deep
}
}
} else {
$result[$k->name] = $this->getSubLevel($key->uid)->row('name');
} // end second level deep
}
} else {
$result = NULL;
}
return $result;
}
private function getSubLevel($id)
{
return $this->db->select('*')->from('binary_tbl')->where('supermember', $id)->get();
}
upon invoking the nestDataIntoArray(1) method i got the following output
OUTPUT
array (size=1)
'A' =>
array (size=2)
'B' =>
array (size=2)
0 => string 'D' (length=1)
'D' => string 'H' (length=1)
'C' =>
array (size=3)
0 => string 'E' (length=1)
'E' => null
'G' => string 'J' (length=1)
this output seems to be fine but i really dont want that Zero index and some of the data still has one or two data related to them which i still have to loop through to get and that to me just seems to be alot of unnecessary coding. So the question is: which other better way can i achieve this and how do i get rid of that zero index?

Providing the Custom Name to both Key and Value Pairs of an Array

I have a table named questions in the following form:
Table Name: questions
qn_id | question |
---------------------------------------------------------------
19 | What is your rating on your Team Work?
20 | What is your rating on your Skills?
21 | What is your rating on your Personal Quality?
I have another table named rating as shown below:
Table Name: rating
id | employee_id | question_id | self_score | supervisor_score
-----------------------------------------------------------------
1 | 205 | 19 | 4 | 3
2 | 205 | 20 | 5 | 4
3 | 205 | 21 | 4 | 5
Note: There are two people involved in providing the score. One is supervisee and another is supervisor.
The score provided by the supervisee is kept in the column named self_score. In the table, employee_id is the id of the supervisee. Supervisor also gives the rating to the supervisee for the same question as shown aboove in the table.
I have generated the data from the database as an Array which is shown below:
$params = Array
(
[selfscore_19] => 4
[supervisorscore_19] => 3
[selfscore_20] => 5
[supervisorscore_20] => 4
[selfscore_21] => 4
[supervisorscore_21] => 5
)
Note: In the key named [selfscore_19] , selfscore_ is the string and 19 is the question id.
Questions are same for both - 'self' and 'supervisor'.
So I have appended the strings named 'selfscore' and 'supervisorscore' with the question_id.
In the array shown below, key is: [selfscore_19] which has been appended with the question_id i.e 19 and
the value is score provided by 'self' which is 4.
And other data follows similar pattern.
Attempt:
The code below shows the attempt done by me so far:
Note: I have only shown the main part of the method.
foreach($params as $key => $value){
$exp_key = explode('_', $key);
if($exp_key[0]=='selfscore'){
$arr_result[] = $value;
}
}
foreach($params as $key => $value){
$exp_key = explode('_', $key);
if($exp_key[0]=='supervisorscore'){
$arr_result[] = $value;
}
}
if(isset($arr_result)){
echo '<pre>';
print_r($arr_result);
echo '<pre>';
}
This is the output of the above code:
Current Output:
Array
(
[0] => 4
[1] => 5
[2] => 4
[3] => 3
[4] => 4
[5] => 5
)
Now I want to tranform the Current Output in the form of following Output.
Although I have already researched about this case, but I am finding it a bit tricky.
What modification should I do to achieve the required output?
Suggestions are highly appreciated.
Required Output:
$score['self_score']=array(
array('question_id'=>19,'score'=>4)
array('question_id'=>20,'score'=>5)
array('question_id'=>21,'score'=>4)
);
$score['supervisor_score']=array(
array('question_id'=>19,'score'=>3),
array('question_id'=>20,'score'=>4)
array('question_id'=>21,'score'=>5)
);
Do it with a single loop. Use the first part of $exp_key as the key of the resulting array, and the second part as the value of the question_id key of the sub-array.
foreach ($arr_result as $key => $value) {
$exp_key = explode("_", $key);
$score[$exp_key[0]][] = array("question_id" => $exp_key[1], "score" => $value);
}
I think I'll recommend that you use a UNION to join two simple queries so that your initial resultset is very close to what you want (close enough to simply iterate and/or modify it).
SQL: (Demo)
(SELECT 'group' AS 'self_score', question_id, self_score
FROM rating
WHERE employee_id = 205
ORDER BY id)
UNION
(SELECT 'supervisor_score', question_id, supervisor_score
FROM rating
WHERE employee_id = 205
ORDER BY id)
Resultset:
group | question_id | self_score
------------------|---------------|------------
self_score | 19 | 4
self_score | 20 | 4
self_score | 21 | 5
supervisor_score | 19 | 3
supervisor_score | 20 | 4
supervisor_score | 21 | 5
If you are open to a PDO solution, fetchAll(PDO::FETCH_GROUP) will come in pretty handy.

Yii relation STAT with multiple columns

i'm trying to get a STAT relation from a Review table. This is my code
public function relations()
{
return array(
'avarageRating' => array(SELF::STAT, 'Reviews', array('make_code'=>'make_code', 'model_code'=>'model_code', 'year'=>'year'), 'select' => 'AVG(overall_rating)'),
}
the table would look something like this
make_code | model_code | year | overall_rating
01 | 02 | 2015 | 4.2
01 | 03 | 2014 | 4.0
01 | 02 | 2015 | 3.0
i want to get the overall_rating average for all rows that have the same make_code, model_code and year
example, make_code 01, model_code 02 and year 2015. (4.2+3.0 / 2), $model->avarageRating should give me 3.6
Right now, when i call the relation using $model->avarageRating; i get an error
preg_match() expects parameter 2 to be string, array given
any idea what i'm doing wrong?
EDITED:
function getavarageRating() {
$criteria = new CDbCriteria();
$criteria->select='ROUND(AVG(overall_rating), 1) AS avg, COUNT(overall_rating) AS total';
$criteria->addCondition("make_code=:make_code");
$criteria->addCondition("model_code=:model_code");
$criteria->addCondition("year=:year");
$criteria->params = array(':make_code' => $this->make_code, ':model_code' => $this->model_code, ':year' => $this->year);
$query = Reviews::model()->find($criteria);
return $query;
}
i added this function in my model, and this workws. but i there a way to use relations instead?
Seems you get a collection for your result so you should access by index , try accessing the first element as
$model[0]->avarageRating;

How to find the best subset from an array whose sum is equal to X number in php

I have an array as
$array = array(3,5,6,10,15,30);
$sum = 69;
then there are 3 different sums that equal 69:
3+5+6+10+15+30,
3+6+10+20+30,
3+6+30+30,
The best one is 3+6+30+30. Because it contains higher number from array to complete the sum that reduce the number count.
(A number can be used within a sum as many times as it appears in the list, and a single number counts as a sum.)
Here is the code that I am implementing
$sum = 18;
$list = array();
$this->sumUpRecursive(array(3,5,6,10,15,30), $list); //function call
$list = array_filter($list,function($var) use ($sum) { return(array_sum($var) == $sum);});
var_dump($list);
function sumUpRecursive($array, &$list, $temp = array()) {
if (count($temp) > 0 && !in_array($temp, $list))
$list[] = $temp;
for ($i = 0; $i < sizeof($array); $i++) {
$copy = $array;
$elem = array_splice($copy, $i, 1);
if (sizeof($copy) > 0) {
$add = array_merge($temp, array($elem[0]));
sort($add);
$this->sumUpRecursive($copy, $list, $add);
}
else {
$add = array_merge($temp, array($elem[0]));
sort($add);
if (!in_array($temp, $list)) {
$list[] = $add;
}
}
}
}
Result:
Array
(
[9] => Array
(
[0] => 3
[1] => 5
[2] => 10
)
[28] => Array
(
[0] => 3
[1] => 15
)
)
I hope this might be bit complex . Its taking a number from array once. But how to figure out for 69...
Thanks
This should work for you:
What does this code do (the function getKnapsackSum())?
1. prepare data
In the first few lines of the function I prepare the data, that means I sort the array DESC with rsort(). I get the last element of the list with end(), reset the array pointer with rest() and assign it to a temp variable.
2. input check
Before I begin to calculate the sum I check that the input isn't 0.
3. calculate the sum
After this the real stuff happens (IT voodoo, not really)! I start with a loop which is false as long as I didn't got the sum. The next 2 lines in the while loop are there to check, that first if the sum can't be calculated, that it returns an array with a 0 and second that when we got a "offset" of the array pointer, that I set it back the last array element.
Then the first if clause is there to check if it made a mistake and it has to try it with lower values. So as an example:
list = [3, 5, 6]
sum = 8
//entire sum
| 0
|
check 6: |
|
6 + sum -> 8 | 6 | fits
6 + sum -> 8 | | does not fit
|
check 5: |
|
5 + sum -> 8 | | does not fit
|
check 3: |
|
3 + sum -> 8 | | does not fit
--------------------------------------------------------
= sum = [6] != 8
As you can see right here with this example the algorithm made a mistake, because it started to build the sum with 6, but after this it couldn't build it until the end, now here is where the first if clause checks, if the current element of the array pointer is the end of the array and this value + the current sum is higher than the goal.
If this is the case it deletes the last value from the sum array and pops off the highest element of the list. So now it tries it again with the following data:
list = [3, 5]
//^ As you can see it removed the highest value of the list
sum = 8
//entire sum
| 0 <- it removed the last value of the sum array, here 6
|
check 5: |
|
5 + sum -> 8 | 5 | fits
5 + sum -> 8 | | does not fit
|
check 3: |
|
3 + sum -> 8 | 3 | fits
3 + sum -> 8 | | does not fit
--------------------------------------------------------
= sum = [5, 3] == 8
So as you can see now the first if clause made it possible to build the sum with the list. So the if statement makes sure that it corrects errors of level 1.
Now the second if statement in my while loop corrects errors of level 2. So what are errors of level 2? We also look again at an example:
list = [3, 5, 6]
sum = 22
//entire sum
| 0
|
check 6: |
|
6 + sum -> 22 | 6 | fits
6 + sum -> 22 | 6 | fits
6 + sum -> 22 | 6 | fits
6 + sum -> 22 | | does not fit
|
check 5: |
|
5 + sum -> 22 | | does not fit
|
check 3: |
|
3 + sum -> 22 | 3 | fits
3 + sum -> 22 | | does not fit
--------------------------------------------------------
= sum = [6, 6, 6, 3] != 22
So as you can see it couldn't build the sum entirely. But this time it isn't an error of level 1, because if we take the last element away from the current sum and go through the new list where we removed the highest element it still can't build the sum as you can see here:
correction of errors level 1:
list = [3, 5]
//^ As you can see it removed the highest value of the list
sum = 22
//entire sum
| [6, 6, 6] <- it removed the last value of the sum array, here 3
|
check 5: |
|
5 + sum -> 22 | | does not fit
|
check 3: |
|
3 + sum -> 22 | 3 | fits
3 + sum -> 22 | | does not fit
|
--------------------------------------------------------
= sum = [6, 6, 6, 3] != 22
So as you can see it is stuck now, it can't correct the mistake only with the first if clause. And here is where the second if statement checks if the list is empty, if this is the case that means that you tried every value, but the mistake is higher up in the sum array.
So now it goes back 1 array element of the sum array and deletes it. It also takes the mistake as offset to get a list without the number which was the mistake. So here: [6, 6, 6, 3] the 3 gets removed from the first if clause so now the array looks like this: [6, 6, 6]. Now the second if statement see's that the mistake was 6. It removes it and also corrects the list where it chooses the numbers from.
So now the result array looks like: [6, 6] and the list to choose numbers from like this: [5, 3]. And now that it made a correction of level 2 it can build the sum as you can see here:
list = [3, 5]
//^ As you can see it removed the highest value of the list
sum = 22
//entire sum
| [6, 6] <- it removed the last value of the sum array, here 3 and 6
|
check 5: |
|
5 + sum -> 22 | 5 | fits
5 + sum -> 22 | 5 | fits
5 + sum -> 22 | | does not fit
|
check 3: |
|
3 + sum -> 22 | | does not fit
|
|
--------------------------------------------------------
= sum = [6, 6, 5, 5] == 22
So after this the if else statement is there just to check if the current value of the list fits into the sum array and isn't bigger than the goal. If it fits it adds it to the array otherwise it goes to the next list element.
Now as you can see my code corrects a few errors, but I'm not 100% sure that it works for everything and I'm also not sure if you can produce errors of level 3 where you have to go back in the sum array an correct 3 values, and if there is one I'm also not sure if my code corrects it or maybe even fall into a endless loop.
But after all this talking here is the code which does all the magic:
<?php
//data
$arr = [3,5,6,10,15,30];
$sum = 69;
//get sum
function getKnapsackSum($arr, $sum) {
//prepare data
rsort($arr);
$end = end($arr);
reset($arr);
$tmp = $arr;
$result = [];
//check if it is not a empty input
if($sum == 0 || empty($tmp) || array_sum($tmp) == 0) return [0];
//calculate the sum
while(array_sum($result) != $sum) {
if(empty($tmp) && empty($result)) return [0];
if(current($tmp) === FALSE) end($tmp);
//correction for errors level 1
if(current($tmp) == $end && array_sum($result) + current($tmp) > $sum) {
array_pop($result);
array_shift($tmp);
reset($tmp);
}
//correction for errors level 2
if(empty($tmp)) {
$mistake = array_pop($result);
if($mistake == NULL) return [0];
$tmp = array_slice($arr, array_search($mistake, $arr)+1);
reset($tmp);
}
if(array_sum($result) + current($tmp) <= $sum)
$result[] = current($tmp);
else
next($tmp);
}
return $result;
}
$result = getKnapsackSum($arr, $sum);
print_r($result);
?>
Output:
Array ( [0] => 30 [1] => 30 [2] => 6 [3] => 3 )
Also here a few examples of inputs and there outputs from my code:
input | output
------------------------------------
list: [] |
goal: 0 | sum: [0]
------------------------------------
list: [] |
goal: 1 | sum: [0]
------------------------------------
list: [0] |
goal: 1 | sum: [0]
------------------------------------
list: [0] |
goal: 0 | sum: [0]
------------------------------------
list: [3, 5, 6] | //error level 1
goal: 8 | sum: [5, 3]
------------------------------------
list: [3, 5, 6] | //error level 2
goal: 22 | sum: [6, 6, 5, 5]
------------------------------------
list: [5, 7, 9] | //can't build the sum
goal: 56 | sum: [0]
------------------------------------
list: [5, 7, 9] |
goal: 34 | sum: [9, 9, 9, 7]
------------------------------------

How to print specific array entry using variable for position e.g. $array[$x]

With help from others on here, I've got a nested loop on the go that pull a list of months from one sql table and then, for each of those months, it goes through an events table and pulls the respective events.
Table structures are along the lines of:
MonthTable
ID | MonthShort | MonthLong
1 | 2012Oct | October 2012
2 | 2012Sep | September 2012
EventTable
ID | MonthID | Event | Guests | Adults | Children
1 | 1 | Wedding | 200 | 150 | 50
2 | 1 | Bar Mitzvah | 100 | 50 | 50
3 | 1 | Funeral | 100 | 50 | 50
4 | 2 | Birthday | 50 | 30 | 20
5 | 2 | Birthday | 300 | 200 | 100
6 | 2 | Wedding | 200 | 180 | 20
My loop works so that it populates menu A with all available months, then populates menu B with all of the events for that month. You can then click on the event and it displays the relevant information - this is where I'm a bit stuck.
The arrays I've got are similar to the following, the guests array is what I'm trying out atm:
$events = array();
$months = array();
$guests = array();
while ($row = mysql_fetch_array($result)) {
$months[$row["MonthID"]] = $row["MonthLong"];
$events[$row["MonthID"]][] = $row["Event"];
$guests[$row["MonthID"]][] = $row["Guests"];
}
I use a foreach to populate menu B with ($events[$x] as $event). The screen for each event will have an entry similar to the following and this is what I'd like to do (obviously I know this won't work bu it should serve for illustrative purposes):
echo ' Number of guests: ' . print_r($guests[$x])
With guests and events both on the same counter I though it would allow me to print the array entry in the relevant position.
So what I'd like it if you click on "October 2012" and then select "Funeral", the screen would say:
Number of guests: 100
There are actually several dozen records per event but no point going into all of them...
Apologies for the rambling and if this makes no sense! I'm new to PHP and am only really stuck on this bit.
SQL query is built on the following:
$sql = "
SELECT
a.id, b.id AS monthId, a.event, b.monthshort, b.monthlong
FROM
events_table_name AS a
INNER JOIN
month_table_name AS b ON b.id = a.monthId
ORDER BY
b.id, a.id ASC
";
You need make use of the index in the foreach statement. I mean
foreach ($events[$x] as $i => $event) {
...
echo ' Number of guests: ' . print_r($guests[$x][$i]);
}
I would go for a different data structure in PHP. How about this? You might have to change your SQL query to get it, but this is the data structure I'd aim for:
$months = array(
'1' => array(
'long' => 'October 2012',
'events' => array(
'1' => array(
'name' => 'Wedding',
'guests' => '200'
),
'2' => array(
'name' => 'Bar Mitzvah',
'guests' => '100'
),
'3' => array(
'name' => 'Funeral',
'guests' => '100'
)
)
),
'2' => array(
// etc.
)
);
This way, you're able to look up a month; for each month, its events; for each event, its attendance and name.

Categories