For Loop Stops after First Iteration - mysql

I've got this for loop here that stops the loop after the first loop due to the value of $due = 0. If value of $due is anything other than 0, the loop runs fine and everything works--problem is, this condition must always be zero. Bangin' my head against the wall on this one. Any ideas? Here's the loop:
for ($i = 0; $i < $unpaid->getInvoiceQuantity($customer_id); $i++) {
$each_invoice_id = $request->input('invoice_id' . $i);
$whats_due = DB::table('invoices')
->select('due')
->where('id','=', $request->input('invoice_id' . $i))
->first();
$invoice_payment_total = $request->input('total' . $i);
$inv_id_array = array('invoice_id' => $request->input('invoice_id' . $i), 'payment_id' => $payment_id,
'no_invoice' => false);
DB::table('payment_applications')->insert($inv_id_array);
$due = 0;
if ($whats_due->due == $invoice_payment_total) {
$due = 0;
}
if ($whats_due->due > $invoice_payment_total) {
$due = $whats_due->due - $invoice_payment_total;
}
$update_array = array('due' => $due);
DB::table('invoices')->where('id', $request->input('invoice_id' . $i))
->update($update_array);
$payment_application_update_array = array('amount' => $request->input('total' . $i));
DB::table('payment_applications')->where('invoice_id', $request->input('invoice_id' . $i))
->update($payment_application_update_array);
}

One of the updates must be changing the invoice quantity, and making it lower than $i, so the loop condition is no longer met.
You should save the value in a variable rather than calling the method every time.
$quantity = $unpaid->getInvoiceQuantity($customer_id);
for ($i = 0; $i < $quantity; $i++) {
// rest of loop
}

Related

What's the best approach to display price ($$$) dynamically from table?

I have a table field that stores the price range. (Out of 5)
I want to display it in this manner.
If the range is 3, then display $$$ and other 2 ($) muted.
What is the best approach or what is this called?
(Check the below image for reference)
You could make use of for loop as follows:
$range = 3;
for($i=0; $i<5; $i++){
if($i < $range){
echo "<strong>$</strong>";
}else{
echo "<span class='text-muted'>$</span>";
}
}
and you have to add CSS like:
.text-muted {
color: #777;
}
Update
You can also use it as a function:
<?php
function displayRangeAsDollar($range){
$boldText = '';
$mutedText = '';
for($i=0; $i<5; $i++){
if($i < $range){
$boldText .= '$';
}else{
$mutedText .= '$';
}
}
return "<strong>".$boldText."</strong>"."<span class='text-muted'>".$mutedText."</span>";
}
echo displayRangeAsDollar(3);

Entering an array to the firstOrCreate generates an error Laravel 5.7

I am running the firstOrCreate on my controller with the following code:
private function validateNumberBD($areaCodes,$numbers){
$arrayAreaCodes = array();
foreach ($areaCodes as $key => $value) {
$arrayAreaCodes[] = $value->AREACODES_ID;
}
$consultArray = array();
for($i = 0; $i < count($numbers); $i++){
for($j = 0; $j < count($arrayAreaCodes);$j++){
$consultArray[] = (['PHONE' => $numbers[$i],'AREACODES_ID' => $arrayAreaCodes[$j]]);
}
}
//dd($consultArray);
$searchOrCreate = Phone::firstOrCreate($consultArray);
}
My problem is generated since executing that code generates the following error:
If I do a dd () to my $ consultArray variable, it shows me the following array
If I change the position of the array values, I get this error:
Consulting the new array would look like this.
I think my mistake is in how to list the data, but I really don't know what else to do.
In query mode, how do I know how many values ​​the firstOrCreate creates for me?
firstOrCreate cannot check or insert multiple records and you are sending an array of arrays.
for($i = 0; $i < count($numbers); $i++){
for($j = 0; $j < count($arrayAreaCodes);$j++){
$searchOrCreate = Phone::::firstOrCreate(
['PHONE' => $numbers[$i], 'AREACODES_ID' => $arrayAreaCodes[$j]]);
}
}
This could work.

Yii2 ActiveRecord add a new record with unique text field

I am using Yii2 and ActiveRecord. I have a field called "code" and for each record, it is meant to have a unique value like this: "REC0001", "REC0002", "REC0003" in a sequencial manner.
All works and I can generate a record code as described. However if I refresh my page request fast in a multiple manner (trying to test multiple requests at the same time in a very raw manner hehe), then some of the records end up with the same record code. In other words I found "REC007" a few times.
I generate the code looking at the last code and increase it by one, then I do a while foundFlag == true by checking to see if it already exists in the database.
I am suspecting there is a delay in writing to the database and hence it assumes that it is not there.
Here is a portion of the code:
static function createCode($rec){
if ($rec->code){
return $rec->code;
}
if ($rec->id){ // find it by id if one passed and record exists
$tmpRec = $rec->find()
->where([
'id' => $rec->id,
])
->one();
if ($tmpRec && $tmpRec->code){
return $tmpRec->code;
}
}
$prefix = 'REC';
if (!$prefix){
$prefix = 'REC';
}
$maxDecimals = 12;
$codeLength = $maxDecimals+strlen($prefix);
$query = $rec->find();
$query = $query->where([
'archived' => '0'
]);
// look under an organization if it exists in the model and there is one
if ($rec->hasField('organization_id') && $organization_id){
$query = addQueryWhere($query, [
'organization_id' => $organization_id,
]);
}
$query = addQueryWhere($query, [
'LENGTH(code)' => $codeLength*1,
]);
$query = $query->orderBy('code desc');
$lastRec = $query->one();
$tmpNumber = 0;
if ($lastRec && $lastRec->id){
// check what it returns
$tmpNumber = str_replace($prefix, '', $lastRec->code);
}
$tmpNumber++;
$leftDecimals = $maxDecimals - strlen($tmpNumber.'');
for ($k=0; $k <= $leftDecimals-1 ; $k++){
$tmpNumber = '0'. $tmpNumber;
}
$ret = $prefix . $tmpNumber;
return $ret;
}
public function generateCode($rec){
$foundFlag = true;
$break = 1000; // safe break point - no continuous loop
$cnt = 0;
$code = static::createCode($rec);
while ($foundFlag === true || $cnt < $break){
$tmpRec = $rec->find()
->where([
'code' => $code,
])
->one();
if (!$tmpRec->id){
$foundFlag = false;
break;
}
$time = getCurrentTimestamp();
$code = static::createCode($rec);
$cnt++;
}
$ret = $code;
return $ret;
}
So I simply call: $this->code = $this->generateCode();
Like I said it does work in generating the code, but it creates duplicates when it shouldn't!
Thank you for your assistance.

code igniter active records - help streamlining process

I am currently using the below code to get a list of uuid's then split them into groups of 1000, then insert those groups into the database.
This works fine except this has to work on at times, over a million uuid's
The issue is this uses a massive amount of memory, so I need help to streamline this process to use less memory...
public function send_daily_email($dealId) {
set_time_limit(0);
$deal = $this->ci->deal->get($dealId);
if ($deal == false)
throw new exception('Unknown Deal Specified');
$users = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->get();
if ($users->num_rows() == 0)
throw new exception('No users in region');
$message = $this->ci->load->view('emails/daily', array('name' => $deal->title, 'content' => $deal->snippet), true);
$uuids = array();
foreach ($users->result() as $u)
$uuids[] = $u->uuid;
$uuids = array_chunk($uuids, 1000);
$sendId = 0;
foreach ($uuids as $batch) {
$count = count($batch);
$this->db->set('dealId', $dealId)->set('content', $message)->set('regionId', $deal->region)->set('recipients', $count)->set('created', 'NOW()', false)->set('status', 'Creating');
if ($sendId === 0) {
$this->db->insert('dealEmailParent');
$sendId = $this->db->insert_id();
$this->db->set('sendId', $sendId)->where('id', $sendId)->update('dealEmailParent');
}
else
$this->db->set('sendId', $sendId)->insert('dealEmailParent');
$insert = array();
foreach ($batch as $uuid)
$insert[] = array('parentId' => $sendId, 'uuid' => $uuid);
$this->db->insert_batch('dealEmailChild', $insert);
}
}
I hate to say this, but from what I know about CodeIgniter, the only way it knows to fetch results is to fetch the entire resultset at once, even if you only need one row, or even if you want to fetch a row at a time and do some processing. It doesn't operate with cursors as the native mysql(i)/PDO functionality does.
For this large a dataset, I'd suggest sticking to the native PHP database functions and foregoing CodeIgniter's active record database classes.
This reworking can insert 1,000,000 "users" in under a minute without any memory limits :)
public function create_daily_email($dealId)
{
$time_start = microtime(true);
set_time_limit(0);
$deal = $this->ci->deal->get($dealId);
if ($deal == false)
throw new exception('Unknown Deal Specified');
$message = $this->ci->load->view('emails/daily', array('name' => $deal->title, 'content' => $deal->snippet), true);
$start = 0;
$end = 50000;
$q = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->limit($end, $start)->get();
$sendId = 0;
while ($q->num_rows() != 0) {
//do stuff
$uuids = array();
foreach ($q->result() as $u)
$uuids[] = $u->uuid;
$uuids = array_chunk($uuids, 1000);
foreach ($uuids as $batch) {
$count = count($batch);
$this->db->set('dealId', $dealId)->set('content', $message)->set('regionId', $deal->region)->set('recipients', $count)->set('created', 'NOW()', false)->set('status', 'Creating');
if ($sendId === 0) {
$this->db->insert('dealEmailParent');
$sendId = $this->db->insert_id();
$this->db->set('sendId', $sendId)->where('id', $sendId)->update('dealEmailParent');
$parentId = $sendId;
}
else {
$this->db->set('sendId', $sendId)->insert('dealEmailParent');
$parentId = $this->db->insert_id();
}
$insert = array();
foreach ($batch as $uuid) {
$insert[] = array(
'parentId' => $parentId,
'uuid' => $uuid
);
}
$this->db->insert_batch('dealEmailChild', $insert);
}
//stop stuff
unset($q);
unset($uuids);
unset($insert);
$start = $start + $end;
$q = $this->db->select('uuid')->from('userRegionLink')->where('regionId', $deal->region)->limit($end, $start)->get();
}
$this->db->set('status', 'Pending')->where('sendId', $sendId)->update('dealEmailParent');
$time_end = microtime(true);
$time = $time_end - $time_start;
die("Did nothing in $time seconds");
}

How can I paginate within a while loop?

I basically need to have take some videos information out of a database with a while loop and put them into a div. The only issue is that I need to put only 6 at a time in between a and tag and have it go to the next 6 and so forth. Here's my code:
$count = 0;
$sql = "SELECT * FROM videos ORDER BY id DESC";
$result_set = $database->query($sql);
while($videos = $database->fetch_array($result_set)) {
$count++;
// i know this is horribly wrong...
if($count == 0 || (($count % 6)+1 == 1)) {
echo '<div>';
}
// i need 6 videos to go in between the <div> and </div> tags then go on to another 6
echo "{$videos['title']}";
if($count == 0 || (($count % 6)+1 == 1)) {
echo '<div>';
}
}
This is an efficent way to do what you want:
$resultPerPage = 6;
$count = 0;
$sql = "SELECT * FROM videos ORDER BY id DESC";
$result_set = $database->query($sql);
$noPage = 1;
echo '<div id="page_1" class="pages">';
while($videos = $database->fetch_array($result_set)) {
$count++;
echo "{$videos['title']}";
if($count == $resultPerPage) {
echo '</div><div id="page_' . $noPage++ . '" class="pages">';
$count=0;
}
}
echo '</div>';