I'm new to OOP and classes.

Here is what I have, I have a car class, make, model, mileage, cost etc.

I also want a method to call all cars.

Do I need a new class with a method which calls the cars class and passes in multiple objects or can I have a method within the cars class and pass in multiple instances of itself?

    If all the new class does is call methods on instances of the cars class then it might as well just be the cars class. A static method in the Cars class would have the advantage of being able to call any instance method of an individual car, including protected and private ones.

    static function callingAllCars(array $cars)
    {
        foreach($cars as $car) {
            $car->see('The man');
        }
    }
    

      Not exactly, I have

      class cars{
          public $make;
          public $plate;
          public $miles;
          public $unitcost;
          public $colour;
      
          public function getPlate(){
              echo $this->plate;
          }
      protected function getAllCars(){
              $sql = "SELECT * FROM cars";
              $result = $this->connect()->query($sql);
              $numrows = $result->num_rows;
              if ($numrows > 0){
                  while($row = $result->fetch_assoc()){
                      $data[] = $row;
                  }
                  return $data;
              }
              
      
          }
      
      }

      This is just an example but will look up a database and return plate number and maybe make colour year etc.

      What I also want a method to get all cars. I think I need to return an array of cars in my cars class but then use a second class to use it?

      class carsList extends cars{
      public function showAllCars(){
              $datas = $this->getAllCars();
              foreach ($datas as $data){
                  echo $data['ID'];
              }
          }
      }

        First of all, I don't think carsList extends cars, unless every method in cars is meaningful when called on an instance of carsList (what should happen when you call $carslist->getPlate()?). Conversely, getAllCars() doesn't belong in cars because it represents one car: you have to construct a car to use the method. (I'm assuming from the list of properties like $plate that a cars is actually just one Car.)

        Instead of returning an array of cars, and since you already have a carsList class, make that your "second class". Store the list of cars as an array property of the $carsList object (it's already called carsList so it won't be a surprise to find that it represents a list of cars) and have whatever functions are intended to act on lists of cars would be methods of that class. You could even have a method to return that array for functions that will want access to that list without putting the function in the class. The getAllCars() would be a static property of CarsList that returns a CarsList instance (it would contain a call to the constructor) which then has the instance methods that apply to lists of cars.

        At the moment you only have use for one carsList object at a time—one that lists all cars in the table. With a bit of work you could have a $carsList object for any list of cars (meeting certain criteria, chosen in some fashion, filtered from another list etc.), and then use the object any time you want to represent a list of cars.

          Cheers for your help. As I said I'm new to this and I'm a bit confused.

          I have cars class now, It contains basic properties of the car, colour, make rego etc. Methods will be added.

          I have a second file with a second class now called carList. This will be a list (array) of objects (cars) retrieved from a database. I want to drill into each object and get the colour or make etc.

          Creating a car object is easy.

          `$car = new cars();
          $car->cost = 14000;
          $car->make = "Honda";
          $car->rego = "ABC1234";`

          Now with my second class, I'm returning an array of data

          `class carslist extends database {
          
             public function getCars(){
              $sql = "SELECT * FROM cars";
              $result = $this->connect()->query($sql);
              $numrows = $result->num_rows;
              if ($numrows > 0){
                  while($row = $result->fetch_assoc()){
                      $data[] = $row;
                  }
                  return $data;
              }
             }
           }
          $ac = new carslist();
                  print_r( $ac->getCars() );

          This returns an array of data but not a car object. Am i hopelessly lost on this topic. I think I know what I want to do but can't work out how.

            Okay, here is what I have, could really value your thoughts on it.

            class cars {
            
               public $cost;
               public $make;
               public $rego;
               
               function __construct($cost, $make, $rego){
                  $this->cost = $cost;
                  $this->make = $make;
                  $this->rego = $rego;
               }
            
            }

            list class

            class carsList extends database {
                
                public $carList = array();
            
                public function addCar($c){
                    array_push($this->carList, $c);
                    return $this->carList;
                }
            
                public function showList(){
                    return $this->carList;
                }
            
               public function getAllCars(){
                $sql = "SELECT * FROM cars";
                $result = $this->connect()->query($sql);
                $numrows = $result->num_rows;
                if ($numrows > 0){
                    while($row = $result->fetch_assoc()){
                        $car = new cars($row['ID'], "Honda", "ABC1234");
                        array_push($this->carList, $car);
                        unset($car);
                    }
                    return $this->carList;
                }
               }
               
            
            }

            My code to test it which seems to be working as expected

            $car = new cars(14000, "Honda", "ABC1234");
                    $car2 = new cars(27000, "Mazda", "GDS212");
                    print_r($car);
                    
                    $ac = new carslist();
                    $ac->addCar($car);
                    $ac->addCar($car2);
                    var_dump( $ac->showList() );
            
                    echo "<hr>";
            
                    var_dump( $ac->getAllCars() );

              Random thoughts/suggestions:

              I'd rather see you pass your database object to CarList's constructor instead of having it extend Database. (I.e.: favor composition over inheritance.)

              class CarList {
                private $db;
              
                public function __construct(Database $db) {
                  $this->db = $db; // use $this->db whenever you need to access DB methods
                }
              }
              
              // example
              $db = new Database();
              $carList = new CarList($db);
              

              I'd add type-hinting to the addCar() method, e.g. public funciton addCar(cars $c) {.

              For extra credit, you could look into implementing the Iterator interface on your list class. It would allow you to then do something like:

              $cars = new CarList($database);
              // add cars, or populate will all cars, then:
              foreach($cars as $car) {
                // do something with each $car object
              }
              

              PS: Nitipick:

              I'd call the class Car, not cars, since it only represents one thing, plus the widely used style is to give class names an initial capital letter. Similarly, it would be CarList; and for that matter: Database. 🙂

              Love it! Thank you.

              It's all working. I have another question but i'll create a new topic for anyone else reading these in future.

                Write a Reply...