I have been working on this for almost three days with no good result. I am trying to get this done in Laravel. But I am looking for any type of good ideas.
I have a product that has a MSRP price. The price for every product drops 10 percent every single day since the product was posted, to the hour.
But i would like to show the price drop for every day as you can see in the picture posted.
Here are some way i have been trying to do it. None of them seem very clean.
Add 1 extra row to the database and call it price. - write a CRON that will run every hour on the server looking at the all the products and setting the new price in that table. But that will mean that I will be using a lot of resources from the server.
Add 10 extra rows in the database and generate the prices when the product is added. However I am having an issue trying to figure out how to show what day it is and highlighted in red. I am guessing I could do this via jquery. Dont know it well but will that be a way?
Pull the products from that database and then cycle through each one and use this code that will generate the table and prices. But than again if the flow of traffic is huge it will eat a lot of the server.
Any other ideas? Anything will help that can help me streamline this.
Here is the code I was able to come up with for the 3ed options. As i dont know jquery i dont have one for the second one.
$msrp = 29.59;
$dayposted = "2016-1-26";
$cDate = Carbon::parse($dayposted);
$today = $cDate->diffInDays();
$days = [];
$i = 1;
$percent = 0;
for($n=0 ;$n<10; $n++) {
setlocale(LC_MONETARY, 'en_US.UTF-8');
if ($i == $today) {
$day = array_add(['day' => 'Day '.$i], 'price' , number_format( $msrp * ((100-($i*10))/100),2, '.', ''));
$day = array_add($day, 'class', 'today');
$price = number_format( $msrp * ((100-($i*10))/100),2, '.', '');
}
elseif($i == 10) {
$day = array_add(['day' => 'Final'], 'price' , number_format( $msrp * ((100-($i*10))/100),2, '.', ''));
$day = array_add($day, 'class', '');
}
else{
$day = array_add(['day' => 'Day '.$i], 'price' , number_format( $msrp * ((100-($i*10))/100),2, '.', ''));
$day = array_add($day, 'class', '');
}
array_push ($days, $day);
$i++;
}
Also here is what I am looking to get done.
Press here to see the image
The answer is it depends on when you want the work to be done (the calculation).
I agree that doing the calculation every time a user requests the information if you don't have to is an obvious waste of resources. However, mathematical calculations are not very intensive so long as you're not doing a lot of iterating, querying or worst of all counting things in the database.
That being said, if you really want to make sure these calculations don't bog down your server the solution I'd suggest is to do it on the client.
You return the raw data to the client and calculate the pricing on the browser, this way the calculation is done off the server and only when requested. This may not be an option, however, because you may not want to expose your pricing method to the client. Still, a simple javascript function that just calculates the % reduction based on a difference between now and the date posted would be easiest.
Regardless, this might be a case of micro-optimization. If you're concerned, do some benchmarks and see how your server handles it under load. That's the only way to know for sure if this optimization is necessary or not.
Related
I can't figure out how to efficiently get SQL data for a Room/Rates/Dates=Amount...
First I load all the "RateData" for a date range with a PDO select. There are many rows, for many rooms, each with many rates... maybe, or maybe it is all empty except a couple of Amounts. It needs to display $0 for missing dates, so next...
I load the Rooms with PDO and loop through them, and for each room I load the Rates with PDO and loop through them (not a ton of rates per room, and not a ton of rooms, but possibly a very long date-range).
So then I loop through the date range and add $0 to the giant UI grid of Amounts by Rate/Date, nested under each Room. I have to do this anyway, as I also have a ton of logic on what to display in the parent Room row that averages the Rates and such.
So what I need to do is instead of using $0, I need to see if the Room/Rate/Date exists in RateData...
$RateAmount = 0;
$RateDataRow = $RateData.filter('Room=1 && Rate=1 && Date=2022-10-01');
If ($RateDataRow exists) {$RateAmount = $RateDataRow['Amount']}
How to I write the above sudocode in PHP?
The only alternative I can think of would be to do 1000's of SQL calls to populate the grid... which seems bad. Maybe it is not that bad though if PDO caches and doesn't actually query the DB for each grid cell. Please advise. Thanks.
I tried this:
$currcost = 0;
//if $ratedata exists for currdate + currrate + currroom
function ratematch($row)
{if (($row['RoomType_Code']=$currrate)
&& ($row['RatePlan_Code']=$currroom)
&& ($row[ 'Rate_Date']=$currdate->format("Y-m-d")))
{return 1;}
else {return 0;}
}
$match = array_filter($ratedata, 'ratematch');
if (!empty($match)) {$currcost = $match['Rate_Amount'];}
But got an error about redeclaring a function. I have to redeclare it because it is in a loop of currdate under a loop of currrate under a loop of currroom (about 1000 cells).
I made it work, I just have to manually loop through the RateData...
//Get Amount from DB
$currcost = 0;
foreach($ratedata as $datarow)
{if (($datarow['RoomType_Code']==$currroom)
&& ($datarow['RatePlan_Code']==$currrate)
&& ($datarow[ 'Rate_Date']==$currdate->format("Y-m-d")))
{$currcost = $datarow['Rate_Amount'];
break;
}
}
If anyone knows a more efficient way to "query" a previous query without a trip to the SQL server, please post about it. Looping through the fetchAll 1000's times seems bad, but not as bad as doing 1000's of WHERE queries on the SQL Server.
I suppose I could make a 3-dimentional array of $0, then just loop through the RateData once to update that array, and finally loop through the 3-dimentional array to do my other calculations (average rate per room per week sat-sun). Sounds hard though.
I have a code that looks like this:
$dagtidhelg = gmdate('H:i', $diffMorning) . "\n";
$kvallstidhelg = gmdate('H:i', $diffNight);
This code runs several times per page since its runt every time a row is loaded from mysql.
It can return a time value ie 08:15 and 09:30. This is the lenght of two work sessions.
That works great but now Im stuck, I want to display the total of every work session at the bottom. I have tried this:
$dagtidhelgtotal = $dagtidhelgtotal + $dagtidhelg;
$kvalltidhelgtotal = $kvalltidhelgtotal + $kvallstidhelg;
But that only adds the hours togheter, it wont even display the :
So Im guessing that Im doing this totaly wrong.
How can I add these times togheter? Maybe convert them to minutes, then add them all togheter?
Add duration together is simple .But you must keep in mind that duration and date are two things completely different. You can write 100:08 for duration but not for date. If your purpose is to keep a duration counter on(one or) every page(s) you need to build a system based on $_SESSION variable.
To add two duree you can proceed like this:
function addDuration($duration1,$duration2){
$result=array_map(function($x,$y){return sprintf("%'.02d", $x+$y);},explode(':',$duration1),explode(':',$duration2));
if($result[1]>60){
$result[0]=sprintf("%'.02d",$result[0]+(int)$result[1]/60);
$result[1]=sprintf("%'.02d",$result[1]%60);
}elseif($result[1]==60){
$result[1]="00";
$result[0]=sprintf("%'.02d",$result[0]+1);
}
return join(':',$result);
}
and the usage in your case could be:
$dagtidhelgtotal = addDuration($dagtidhelgtotal,$dagtidhelg);
if we suppose that
$dagtidhelgtotal ==='100:09' && $dagtidhelg === '08:08'
then after the addition
$dagtidhelgtotal will be equal to '108:17';
I assume, I need Ajax and jQuery to show new data based on date after clicking a button.
What I want to do is something like this:
<< January 15................today: January 16..............January 17 >>
Data4
Data5
Data6
When I click "January 17" data 4-6 should change to data 7-9 because data 7-9 is added to the MySQL database on January 17.
Of course I have a code to query the database and show today's data, but I am going crazy about not being able to reload the page with new data.
I tried to search the whole internet, but nothing I can find fits my needs.
Your question has a lot of sides to it. This answer's solely purpose to demonstrate how front end, back end and persistence layer communication works.
DO NOT USE THIS IN PRODUCTION! THIS CODE IS SHITTY AND FOR DEMO PURPOSES ONLY!
Modern web applications are not implemented like this. Front end frameworks/libraries are commonly used to keep complexity manageable.
First of all your back end should provide an API to the front end.
Lets assume your back end accepts the following HTTP GET request:
www.example.com/users/list_by_date/20150131
The last parameter is a date in YYYYMMDD format. Upon receiving this request, your back end sends a pre-rendered HTML snippet containing a list of users from that date. (Nowadays front end side rendering is quite popular and you should look into that topic as well. In this case your back end sends a list of users in JSON format which is then rendered on the front end side using templates. Adding code for this would make example even more complex).
In order to get this list of users, you initiate an AJAX request from the front end when a user clicks on a next-day button (which in your example contains "January 17"). Furthermore, you need to replace a list of currently shown users from January 16th with the new ones. Lets assume that list has a class attribute .users in HTML code. Here is a front end code using jQuery:
$(function() {
$(document).on('click', '.next-day', function() {
$.getJSON("/users/list_by_date/20150131", renderResults);
});
function renderResults = function(data) {
$('.users').html(data); // replaces old contents with the new ones received from server
};
});
You should also update prev/next link titles to the next dates, January 16th and January 18th respectively.
On the back end side, you execute a SQL statement to fetch a list of users. It could look something like this:
SELECT * from Users where DATE(datetimecolum) = '2015-01-17'
The exact way to put an attribute into a SQL query varies among programming languages/frameworks.
This should help you start working on your own solution. You probably should at least consider a front end framework/library to help you manage the complexity. You might want to spend a few days or even weeks getting familiar with front end technologies before attempting to implement a good solution on your own. It might be more cost efficient to hire a front end developer.
I did it on my own and the code actually were 5 lines.
I needed 2 days. Somebody who knows it, could have written it up in 2 minutes. So thanks for all the fish!
Here is the code, if somebody ever needs something like this:
The code for determining the very last date available (which I had already):
$query = mysqli_query($bd, "SELECT MAX(datum) as max_datum, MIN(datum) as min_datum FROM apps WHERE price = 0 ") or die(mysqli_error());
$maxdate = mysqli_fetch_assoc($query);
$maxdate = $maxdate['max_datum'];
$mindate = $mindate['min_datum'];
The actual code I was looking for to display two links for next and previous days (without design):
$date = isset($_GET['date']) ? $_GET['date'] : $maxdate;
$prev_date = date('Y-m-d', strtotime($date .' -1 day'));
$next_date = date('Y-m-d', strtotime($date .' +1 day'));
if ($date < $maxdate) {
echo "<a href=?date=$next_date>forward a day</a>";
}
if ($date > $mindate) {
echo "<a href=?date=$prev_date>back a day</a>";
}
The code executing the data which I had already:
$result = mysqli_query($bd, "SELECT * FROM apps WHERE datum = '".$date."' AND price = 0 ") or die(mysqli_error());
$count = mysqli_num_rows($result);
echo "<div id='icon-wrapper'>";
$cc = 0;
while ($row = mysqli_fetch_array($result)){
...
$cc++;
if ($cc < $count) {
echo "\n";
}
}
echo "</div>";
mysqli_close($bd);
?>
Any idea of what would be the best way of writing a function in PHP for an online registration system with possibility of objects' occupancy;
Just to be clear:
I want to check the availability of one object in the database by writing a function and by comparing two variables:
Starting time of reservations;
Their duration (finishing time);
So when a new reservation is entered I check the database; if it doesn't pass the limit of objects in that period (by comparing to previous reservations) it gives a message which I will then pass it to JavaScript and enable the Submission button; but if it passes the limit in my JavaScript I'll suggest a duration which is available for the entered Starting Time;
In my current PHP function I am having some problems:
First I am using so many variables and so many loops (which may cause the system slow if it gets bigger) and the code seems quite messy!
It doesn't recognize the difference between serial or concurrent reservations therefore it behaves the same to these reservations.
Here is a snippet of my function:
$reservation = new Reservation;
$reservations = $reservation -> fetch_all();
foreach ($reservations as $reservation) {
for ($j = $res_code['res_code_st']; $j < $res_code['res_code_fi']; $j++) {
for ($i = $reservation['res_code_st']; $i < $reservation['res_code_fi']; $i++) {
if ($i == $j) {
$count = $count + 1;
$arr[] = $reservation['res_code_st'];
$arr[] = $reservation['res_code_fi'];
break 2;
Which actually I'm storing time in this format;
For example for 12:30 I'm storing 1230 or for 09:20 I'm storing 0920 and then I'm checking every minute of any item with every minute of new reservation (everything happens in the same day: Days don't matter!) and in case it finds a match I count it as a new reservation in that period (the reason why it doesn't differ concurrency and serial);
I believe it should be simple but I'm kinda confused and my mind doesn't work for a better solution right now!
Thanks for your times :)
EDIT
I tried the suggested way of #kamil-maraz , I think it saves some time for reducing complexity but I still couldn't figure out how to check the concurrency.
Let me give one example:
There are four possibility of disturbance I try to show in this symbolic figure,
Suppose each line is a reservation across time, first line is for new reservation and next four are already stored in the DB;
Four disturbance are as :
One that starts before and ends at the middle of new request,
One that starts before and ends after the new request;
One that is completely inside the new reservation;
One that starts after the new request and ends after it;
0-----------------0
0--------------------------------0
0--------------0
0----------0
0-----0
$result = $db -> prepare('SELECT Count(reservation_id) FROM reservations WHERE (res_code_st < ? AND res_code_fi > ?) OR (res_code_st > ? AND res_code_fi < ?) OR (res_code_st < ? AND res_code_fi > ?) OR (res_code_st < ? AND res_code_fi > ?)');
$result -> execute(array($res_code['res_code_st'], $res_code['res_code_st'], $res_code['res_code_st'], $res_code['res_code_fi'], $res_code['res_code_st'], $res_code['res_code_fi'], $res_code['res_code_fi'], $res_code['res_code_fi']));
$row = $result -> fetch();
This is giving me the number of reservations in the interval of new request; But what about this case:
0--------------------------0
0-----0
0-----0
0------0
Although in the interval there are 4 reservations which is invalid (Suppose the #object limit == 3 ), but since at each time not more than 2 reservations are made it is still valid (the concurrency problem which I was talking about).
Any idea how should I change the SQL function to fix this ?
It seems to me, that it could be done entirely on the database. You are fetching all results and then you do some magic over data. But you can do it through a database query.
for example somethging like this:
SELECT COUNT(id) FROM reservations WHERE date < ... AND date > ... AND ... etc
then, in the php, you can test count ...
if you want to test different types of reservations, concurent, etc. you can use aggregated table (Like somebedy used here and you can store in rows types of reservations too.
How would I go about programming a daily message on my site that changes daily? I'm thinking of preloading all the messages in a MySQL database.
Any help would be appreciated!
Thanks,
I've tried
$msg_sql = "SELECT * FROM ".TABLE_PREFIX."quotes ORDER BY rand(curdate()) LIMIT 3";
$msg_res = mysqli_fetch_assoc(mysqli_query($link, $msg_sql));
But this only grabs the first MySQL result?
If you want a real message changing daily, you actually don't need to rely on a database or anything fancy. A simple idea might be to create a directory (say /var/www/motds) and populate it with files named YYYY-MM-DD.txt (where YYYY is a 4 digit year number, MM is a two digit month number and DD is a 2 digit day number).
Then, the only thing you need to do in order to display your motd is:
$filename = '/var/www/motds/'.date("Y-m-d").'.txt';
if (file_exists($filename)) {
echo file_get_contents($filename);
}
If you want your daily messages to be taken from a pool of entries (that you can pre-load), you might do something as follows:
$files = scandir('/var/www/motds'); // put files into an array
$messagecount = count($files) - 2; // .. and . shall not be considered
$day = date("z"); // what day do we have today?
echo file_get_contents('/var/www/motds/' . $files[($day % $messagecount) + 2]);
There are plenty of ways to get this done. You list PHP in your tags, so maybe check here:
PHP Script: Quote of the Day
or maybe here