OOP PHP - Converting a function

Morning All

I’ve recently started learning OOP PHP & the MVC design pattern. Coming from Procedural its quite a steep learning curve.

I’m currently re building a site i made with procedural PHP to an MVC framework and was wondering how do i convert a procedural function to OOP?

This is the function…

<?php
$h = date('G'); //set variable $h to the hour of the day
$year = date('Y'); //set variable $year to the current year
//G is the date key for hours in 24 format (not 12), with no leading 0s, like 02.
// Adjust 2 hour offset for MST below.
$h = $h+0;

// MONDAY SCHEDULE
if ($h >= 0 && $h < 4) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h >= 4 && $h < 8) $dynamicaudi = './uploads/herotime/auditt_4-8.jpg';
else if ($h >= 8 && $h < 10) $dynamicaudi = './uploads/herotime/auditt_8-10.jpg';
else if ($h >= 10 && $h < 15) $dynamicaudi = './uploads/herotime/auditt_10-15.jpg';
else if ($h >= 15 && $h < 16) $dynamicaudi = './uploads/herotime/auditt_15-16.jpg';
else if ($h >= 16 && $h < 17) $dynamicaudi = './uploads/herotime/16-17.jpg';
else if ($h >= 17 && $h < 19) $dynamicaudi = './uploads/herotime/auditt_17-19.jpg';
else if ($h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h < 0) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
?>

If someone could advise on how best to write this in OOP it would be much appreciated. Also would i need a controller to target this or would i place this within libraries?

Thanks in advance.

Everything else aside, you have two checks for >=15 and <17, so your first one will never display. Where does $d come from, and why do you create $year and then do nothing with it? And will the hour ever be <0?

When you say “function”, that’s not really how I’d think of a function, in that it just seems to be inline code to me.

Other than that nit-picking, I can’t add anything. I have a bit of an interest in also learning OOP, though I have done bits of it before. In my head, though, I’m struggling to see how you could “convert” that to OOP, I suspect there is more to the question. How does it relate to an object?

Hey Droopsnoot, thanks for the heads up. Was editing late last night so missed that.

You’re absolutely right. This is where i’m getting stuck as i’m brand new to OOP . (Much more comfortable with procedural) but trying to learn OOP & MVC as it seems to be what potential jobs are looking for. I guess that as you said this is more of an object as apposed to a function.

No, that’s not what I was saying. To me, it’s more of a function, it’s just that it’s not written as a function because it doesn’t start as

function chooseimage() { 

and so on. Normally (to me, at least) a function is used when you want to perform the same operation on more than one different set of input data, so you don’t duplicate the code.

1 Like

Thanks Droopsnoot.

You’re absolutely right. This was written in a functions file and called as required but you’re correct i hadn’t declared it as a function.

It’s quite hard to say without knowing the context of this piece of code within the system you are creating.

As alreay mentioned, this is not a function, nor is it an object, it’s just some freestanding code as far as I can see.

A function is defined like: function($arguments){ // code }
An object is defined in a class:-

class myClass {
   public $classProperties

   public function classMethod($arguments){ // code }
}

So the class will contain functions (called methods in that context) that can be carried out on an object.

Making assumptions (not knowing), you may want a schedule class, which may contain a method setImage (among others).

Eg:-

class schedule {
   private $hour;
   private $year;
   private $filePath;
   public $image;
   public $carSlug;

   private function setHour(int $offset = 0){
      $this->hour = date('g')  + $offset ;
      return $this->hour;
   }

   public function setImage(){
      
      if ($this->hour >= 0 && $this->hour < 4) $time = '0-4';
      else if ($this->hour >= 4 && $this->hour < 8) $time = '4-8';
      else if ($this->hour >= 8 && $this->hour < 10) $time = '8-10';
      else if ($this->hour >= 10 && $this->hour < 15) $time = '10-15';
      else if ($this->hour >= 15 && $this->hour < 16) $time = '15-16';
      else if ($this->hour >= 16 && $this->hour < 17) $time = '16-17';
      else if ($this->hour >= 17 && $this->hour < 19) $time= '17-19';
      else if ($this->hour >= 19) $time = '0-4';
      else if ($this->hour < 0) $time = '0-4';

      $this->image = $this->filePath . $this->carSlug . '_' . $time . '.jpg' ;
      return $this->image;
   }
}

Again, this may not be suitable for your needs, but just an example of how objects/classes/functions can be set up in OOP.

1 Like

Good to see the declarations are being used. I hope declare(strict_tyoes); is also used because it saves numerous type tests.

It is also possible to make the method even more robust by specifying the return type.

private function setHour
(
  int $offset = 0
)
:int
{
      $this->hour = date('g')  + $offset ;
      return $this->hour;
}// endfunc

If the exact type is not known then can be found by the following:

echo get_type($this->hour);

This may seem trivial and tedious but does make the function far more instantly readable instead of having to guess and hope for the best after juggling types.

1 Like

What’s interesting to me is that a few of these checks are redundant:

if ($h >= 0 && $h < 4) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
// ... more checks here
else if ($h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h < 0) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';

So basically we can combine $h >= 0 && $h < 4 and $h < 0 into one, to become:

if ($h < 4) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';

So then we have

if ($h < 4) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
// ... more checks here
else if ($h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';

And we can combine that into one again

if ($h < 4 || $h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
// ... more checks here

so then the entire list becomes:

if ($h < 4 || $h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h >= 4 && $h < 8) $dynamicaudi = './uploads/herotime/auditt_4-8.jpg';
else if ($h >= 8 && $h < 10) $dynamicaudi = './uploads/herotime/auditt_8-10.jpg';
else if ($h >= 10 && $h < 15) $dynamicaudi = './uploads/herotime/auditt_10-15.jpg';
else if ($h >= 15 && $h < 16) $dynamicaudi = './uploads/herotime/auditt_15-16.jpg';
else if ($h >= 16 && $h < 17) $dynamicaudi = './uploads/herotime/16-17.jpg';
else if ($h >= 17 && $h < 19) $dynamicaudi = './uploads/herotime/auditt_17-19.jpg';

What’s interesting now is that on the second line, $h >= 4 is always already true, because otherwise the first if would have matched, so that line can be simplified to:

else if ($h < 8) $dynamicaudi = './uploads/herotime/auditt_4-8.jpg';

And the same thing goes for all the checks, so the final result becomes:

if ($h < 4 || $h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h < 8) $dynamicaudi = './uploads/herotime/auditt_4-8.jpg';
else if ($h < 10) $dynamicaudi = './uploads/herotime/auditt_8-10.jpg';
else if ($h < 15) $dynamicaudi = './uploads/herotime/auditt_10-15.jpg';
else if ($h < 16) $dynamicaudi = './uploads/herotime/auditt_15-16.jpg';
else if ($h < 17) $dynamicaudi = './uploads/herotime/16-17.jpg';
else if ($h < 19) $dynamicaudi = './uploads/herotime/auditt_17-19.jpg';

In this result I don’t really like the $h >= 19 at the start anymore. All lines look the same, except for that first one. Let’s put it back at the end to see what happens:

if ($h < 4) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h < 8) $dynamicaudi = './uploads/herotime/auditt_4-8.jpg';
else if ($h < 10) $dynamicaudi = './uploads/herotime/auditt_8-10.jpg';
else if ($h < 15) $dynamicaudi = './uploads/herotime/auditt_10-15.jpg';
else if ($h < 16) $dynamicaudi = './uploads/herotime/auditt_15-16.jpg';
else if ($h < 17) $dynamicaudi = './uploads/herotime/16-17.jpg';
else if ($h < 19) $dynamicaudi = './uploads/herotime/auditt_17-19.jpg';
else if ($h >= 19) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';

Right, but then we don’t need the if anymore, since it’s just the default case now. So:

if ($h < 4) $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';
else if ($h < 8) $dynamicaudi = './uploads/herotime/auditt_4-8.jpg';
else if ($h < 10) $dynamicaudi = './uploads/herotime/auditt_8-10.jpg';
else if ($h < 15) $dynamicaudi = './uploads/herotime/auditt_10-15.jpg';
else if ($h < 16) $dynamicaudi = './uploads/herotime/auditt_15-16.jpg';
else if ($h < 17) $dynamicaudi = './uploads/herotime/16-17.jpg';
else if ($h < 19) $dynamicaudi = './uploads/herotime/auditt_17-19.jpg';
else $dynamicaudi = './uploads/herotime/auditt_0-4.jpg';

So now we have a number and the filename of an image for each hour. What if I stuff that in an array?

$images = [
    4 => './uploads/herotime/auditt_0-4.jpg',
    8 => './uploads/herotime/auditt_4-8.jpg',
    10 => './uploads/herotime/auditt_8-10.jpg',
    15 => './uploads/herotime/auditt_10-15.jpg',
    16 => './uploads/herotime/auditt_15-16.jpg',
    17 => './uploads/herotime/16-17.jpg',
    19 => './uploads/herotime/auditt_17-19.jpg',
];

and now loop it:

$image = './uploads/herotime/auditt_0-4.jpg'; // default
foreach ($images as $hour => $imagePath) {
    if ($h < $hour) {
        $image = $imagePath;
        break;
    }
}

I don’t know about you, but to me that looks a lot simpler and easier to maintain when needing to add more hours etc :slight_smile:

3 Likes

Thanks gents, appreciate your input.

I’ll be honest, at the time of writing that, i had literally just started learning OOP. 11 days in, i now understand it a little bit more. Still a long way to go but appreciate the suggestions. I will take your suggestions on board and modify my code accordingly.

@SamA74, am i correct in thinking that you set the variables to private as they are only required to be called within that class?

@rpkamp, i like what you’ve done there & how it’s been formatted. :wink:.

Thanks again gents.

Yes, functions and properties that are private may only be accessed within the class, public ones may be accessed from outside of the class scope. Protected ones may be accessed from within other classes extended from the class.
The choices made in the example are pretty random, so you will have to decide yourself what to use.

1 Like