Moorcam Posted August 11, 2017 Share Posted August 11, 2017 Hey all, I am trying to get the total number of hours from an array as follows: <?php if(isset($_POST['calculate']) != ""){ class times_counter { private $hou = 0; private $min = 0; private $sec = 0; private $totaltime = '00:00:00'; public function __construct($times){ if(is_array($times)){ $length = sizeof($times); for($x=0; $x <= $length; $x++){ $split = explode(":", @$times[$x]); $this->hou += @$split[0]; $this->min += @$split[1]; $this->sec += @$split[2]; } $seconds = $this->sec % 60; $minutes = $this->sec / 60; $minutes = (integer)$minutes; $minutes += $this->min; $hours = $minutes / 60; $minutes = $minutes % 60; $hours = (integer)$hours; $hours += $this->hou % 24; $this->totaltime = $hours.":".$minutes.":".$seconds; } } public function get_total_time(){ return $this->totaltime; } } $times = array( '02:00:00', '12:15:00' ); $counter = new times_counter($times); echo $counter->get_total_time(); ?> This works fine as is with times just placed inside the array. However, I need to get the times from an object, such as: $times = array( $time1, $time2 ); This will not work because it throws an error - Warning: explode() expects parameter 2 to be string, object given The warning is thrown from here: $split = explode(":", @$times[$x]); Is there a way for me to add all the hours to get a total of the hours? For example: $time1 = 12:00 $time2 = 12:00 Total Hours = 24:00 ,<- This is what I am after. Thanks in advance, Quote Link to comment Share on other sites More sharing options...
Barand Posted August 11, 2017 Share Posted August 11, 2017 What type of objects? What is their structure? Public properties,methods? Give us a clue. Also, the addition process would be easier with DateTime objects $times = [ '05:30:00', '03:15:00', '19:45:00' ]; $now = new DateTime(); $dt1 = clone $now; foreach ($times as $t) { $di = new DateInterval("P0000-00-00T$t"); $dt1->add($di); } $total_time = $now->diff($dt1); echo $total_time->format('%d days %h hrs %i mins'); //--> 1 days 4 hrs 30 mins 1 Quote Link to comment Share on other sites More sharing options...
Psycho Posted August 11, 2017 Share Posted August 11, 2017 Do you plan to use this for arrays or objects? Pick one and code for it. You can always convert one to the other to make the class flexible. $length = sizeof($times); for($x=0; $x <= $length; $x++){ $split = explode(":", @$times[$x]); A foreach() loop should be used for iterating over an array - not building a for() loop that would break if the array did not have sequential indexes starting at 0. You state that your code above works for an array - but I don't see how that is possible. If the array has more than 1 "time" the current code is iterating over each item in the array and redefining the properties for hor, min & sec. THEN the code does the calculation. In other words the result of totaltime is completely based on the last element in the array. Any preceding values are not used in the calculation. Quote Link to comment Share on other sites More sharing options...
gizmola Posted August 11, 2017 Share Posted August 11, 2017 Hey Dan, I think this is a great example of where dependency injection offers a solution to a conundrum. I do have to note that your class has a significant issue. You apparently are trying to reduce the hours into days, but this is currently lossy, as you don't store days anywhere. In this case, let's assume you have this code that works, so long as the data is in a particular format. Now you have data where it doesn't match the format, so you now have a broken class that you are contemplating how to fix. Personally, I'm with Barand 100% that DateTime objects are the way to go in PHP, but there are also cases where you may have tested code that is integrated with a system and can't be easily changed, or where the time/cost and potential breakage of changing things isn't feasible. Now let's assume that your class was this instead of what it is now: <?php class times_counter { private $hou = 0; private $min = 0; private $sec = 0; private $totaltime = '00:00:00'; public function __construct($times){ $this->hou = (int)$times->getHours(); $this->min = (int)$times->getMinutes(); $this->sec = (int)$times->getSeconds(); $this->totaltime = $this->hou . ":" . $this->min . ":" . $this->sec; } public function get_total_time(){ return $this->totaltime; } } Now it is no longer the job of your class to understand the internals of $times. And for $times to work all that is important is that it implements an interface that supports the methods getHours(), getMinutes(), and getSeconds(). Ostensibly, if other code that is working, is calling get_total_time() then you are not going to break your application so long as the format of get_total_time matches what is expected. Just as an aside you might be able to see how a unit test on the class would be very valuable, that insured that the format of get_total_time() was guaranteed to a standard. At any rate, PHP even helps you with this type of exercise by letting you declare an interface: interface timeDataInterface { public function getHours(); public function getMinutes(); public function getSeconds(); } Now to retrofit, you create classes that wrap any time data you need. Class TimeDataArray implements timeDataInterface { public function __construct($times){ private $hou; private $min; private $sec; if(is_array($times)){ $length = sizeof($times); for($x=0; $x <= $length; $x++){ $split = explode(":", @$times[$x]); $this->hou += @$split[0]; $this->min += @$split[1]; $this->sec += @$split[2]; } $seconds = $this->sec % 60; $minutes = $this->sec / 60; $minutes = (integer)$minutes; $minutes += $this->min; $hours = $minutes / 60; $minutes = $minutes % 60; $hours = (integer)$hours; $this->sec = $seconds; $this->min = $minutes; $this->hou = $hours; } } public function getHours() { return $this-hou; } // Add getMinutes(), getSeconds() } Now your exercise in handling any other type of time data is simple: just insure you have a class that implements your interface, and you can pass that into your time_counter class with the expectation that things will work. With PHP type hinting you can now add extra error checking, by insuring that any objects passed to your class actually implement the required timeDataInterface: <?php class times_counter { private $hou = 0; private $min = 0; private $sec = 0; private $totaltime = '00:00:00'; public function __construct(timeDataInterface $times){ .... } Quote Link to comment Share on other sites More sharing options...
Moorcam Posted August 12, 2017 Author Share Posted August 12, 2017 Hi folks, Thanks for the replies. Really appreciate it. Basically, I have the following (one for each day of the week), which gives a total hours worked each day, minus whatever period of time for breaks. It works fine and calculates the difference between the start time and end time and also subtracts the break period from the total. <?php if(isset($_POST['start_shift7']) && $_POST['end_shift7'] && $_POST['break7'] != "") { $datetime1 = new DateTime($_POST['start_shift7']); $datetime2 = new DateTime($_POST['end_shift7']); list($h, $m) = explode(":", $_POST['break7']); $break = new DateInterval("PT{$h}H{$m}M"); $sundiff = $datetime1->add($break)->diff($datetime2); ?> <input type="text" readonly class="form-control" name="sunday" value="<?php echo $sundiff->format('%H:%I'); ?>"> <?php } ?> Now, what I am trying to do, is get the totals from each day, add them together to get a total for the week. I am not very well educated and the Jargon gets me 90% of the time. My apologies for that. Quote Link to comment Share on other sites More sharing options...
Moorcam Posted August 16, 2017 Author Share Posted August 16, 2017 (edited) For anyone interested, I got this working, with the help of a mate, with the following: if(isset($_POST['calculate']) != ""){ class times_counter { private $hou = 0; private $min = 0; private $sec = 0; private $totaltime = '00:00:00'; public function __construct($times){ if(is_array($times)){ $length = sizeof($times); for($x=0; $x <= $length; $x++){ $split = explode(":", @$times[$x]); $this->hou += @$split[0]; $this->min += @$split[1]; $this->sec += @$split[2]; } $seconds = $this->sec % 60; $minutes = $this->sec / 60; $minutes = (integer)$minutes; $minutes += $this->min; $hours = $minutes / 60; $minutes = $minutes % 60; $hours = (integer)$hours; $hours += $this->hou % 24; $this->totaltime = $hours.":".$minutes.":".$seconds; } } public function get_total_time(){ return $this->totaltime; } } $times = array( $mondiff->format('%H:%I'), $tudiff->format('%H:%I'), $weddiff->format('%H:%I'), $thdiff->format('%H:%I'), $fridiff->format('%H:%I'), $satdiff->format('%H:%I'), $sundiff->format('%H:%I'), ); $counter = new times_counter($times); echo $counter->get_total_time(); Edited August 16, 2017 by DanEthical Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.