0

I just started to learn about Objects in PHP. I have the following example PHP for practice. I don't know if I have the structure set-up correctly or not. I want to be able to add to STOPS as mentioned in the commented section at the bottom of the code. I have the SET and GET in here, but maybe something else is missing to access variables like echo $obj->DESTINATION or echo $obj->STOPS[0].

<?php
class EastBound
{
    private $DESTINATION; // Final stop
    private $STOPS;       // Three stops along the way to the final stop.

    public function __construct(){

        $this->DESTINATION = '';
        $this->STOPS = '';
    }

    /* GETTERS */
    public function get_DESTINATION(){
        return $this->DESTINATION;
    }

    public function get_STOPS(){
        return $this->STOPS;
    }


    /* SETTERS */

    public function set_DESTINATION($data){
        $this->DESTINATION = $data;
    }

    public function set_STOPS($data){
        $this->STOPS = $data;
    }
}

$obj = new EastBound();
$obj->set_DESTINATION("Neverland");
$dest = $obj->get_DESTINATION();
echo "Final destination is $dest." . "\n";
var_dump($obj);


/* How do I add these three stops to STOPS?
    For example:
    STOP[0]
        NAME "Radio City"
        TIME "6/16/2013 8:28:00 PM"
    STOP[1]
        NAME "Malt Shoppe Street"
        TIME "6/16/2013 8:31:30 PM"
    STOP[2]
        NAME "Neverland"
        TIME "6/16/2013 8:36:00 PM"
*/ 

?>

Here is the output:

Final destination is Neverland.
object(EastBound)#1 (2) {
  ["DESTINATION":"EastBound":private]=>
  string(9) "Neverland"
  ["STOPS":"EastBound":private]=>
  string(0) ""
}
3
  • I see a getter and a setter, where is your add_stop function? (hint: if you want to add stops, add an adder =) Commented Jun 18, 2013 at 22:57
  • @Mike'Pomax'Kamermans OK. How would I do that? Commented Jun 18, 2013 at 22:59
  • same way the other functions were added. function add_stop($stop) { $this->STOPS[] = $stop; }, with the relevant visbility syntax Commented Jun 18, 2013 at 23:00

3 Answers 3

3

If you want to add exactly three stops, you can call set_stops with a three-element array. That is, however, not very useful. Instead, just add an add_stop() function:

function add_stop($stop) {
  $this->STOPS[] = $stop;
}

and then in your actual script, add three stops:

$obj->add_stop(array('name' => 'Radio City', 'time' => '...'));
$obj->add_stop(array('name' => 'Malt Shoppe Street', 'time' => '...'));
$obj->add_stop(array('name' => '...', 'time' => '...'));

in fact, now we can add as many stops as we want. three, seven, fivehundred... go nuts!

That said, some others have also pointed out that there are certain code style conventions for PHP code, and this code is not following those conventions, making it harder for people who read PHP day in day out to read your code and help you with it. Turn those all-caps variables into lowercase, and try to keep your functions lowercased, too.

If you really wanted, you could make Stop a class too, to do things proper OOP style:

class Stop {
  var $name;
  var $time;
  function __construct($name, $time) {
    $this->name = $name;
    $this->time = $time;
  }
  function get_name() { return $this->name; }
  function get_time() { return $this->time; }
}

with an add_stop that either takes name/time arguments:

$obj->add_stop($name, $time) {
  $this->stops[] = new Stop($name, $time);
}

or takes stop objects:

$obj->add_stop(new Stop("...", "..."));

The latter is the most OOP, really.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, I want to be able to add many stops. How would I then address them? Could I do echo $obj->STOPS[0]->NAME ?
without any visibility rules, yes. If we rename STOPS to stops, it'd be $obj->stops[0]->name (don't use all-uppercase for your variables, that's only for constants). If we want to mark the variables private, then we need to use the getters: $obj->get_stops()[0]->get_name()
Ftr: The following construct only works in php 5.4+: $obj->get_stops()[0]->get_name()
good point. In older versions of PHP you'll have to cache $obj->get_stops() as a local variable first, i.e. $stops = $obj->get_stops(); and then use $stops[0], etc.
3

You are never actually call the stops setter accessor, try this:

 $obj = new EastBound();

 $obj->set_STOPS(
     array(
         array(
             'name' => 'Radio City'
             'time' => '6/16/2013 8:28:00 PM'
         ),
         array(
             'name' => 'Malt Shoppe Street'
             'time' => '6/16/2013 8:28:00 PM'
         ),
         array(
             'name' => 'Neverland'
             'time' => '6/16/2013 8:28:00 PM'
         )
    )
);

It is common place to allow an object the ability access to multiple, related 'attributes'. For this you MUST use arrays. For your specific example, after setting the stops, you could step through each stop later by way of:

foreach ($obj->get_STOPS() as $key => $stop) {

    // Will output: Stop #1: Radio City @ 6/16/2013 8:28:00 PM
    echo sprintf('Stop #%d: %s @ %s', ($key +1), $stop['name'], $stop['time']);
}

9 Comments

So I still need to use arrays to do this with Objects? Or is there another way?
If you want to provide the type of functionality you are seeking, no, you have to use arrays. But it is common place to access arrays associated to a specific instance of the object, like what you are trying to do.
I see so the array is the preferred way.
I think you mean ['name'] and ['time'] ?
ya, I forgot the close quotes.
|
2

If you're going to be writing true OOP, you should use this approach:

/**
 * Class Stop
 * This is an object which represents the "Stop"
 */
class Stop {
    private $name;
    private $time;

    public function __construct($name = '', $time = ''){
        $this->name = $name;
        $this->time = $time;
    }

    /**
     * @param string $name
     */
    public function setName($name) {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getName() {
        return $this->name;
    }

    /**
     * @param string $time
     */
    public function setTime($time) {
        $this->time = $time;
    }

    /**
     * @return string
     */
    public function getTime() {
        return $this->time;
    }
}

class EastBound
{
    /**
     * @var Stop
     */
    private $destination;       // Final stop
    private $stops = array();   // All stops, excluding the final destination.

    /**
     * Constructor
     */
    public function __construct(){ }

    /**
     * Get destination
     * @return string $this->destination
     */
    public function getDestination(){
        return $this->destination;
    }

    /**
     * Set destination
     *
     * @param \Stop $destination
     */
    public function setDestination( Stop $destination ) {
        $this->destination = $destination;
    }

    public function addStop( Stop $stop ) {
        $this->stops[] = $stop;
    }

    /**
     * If you already have a "stop" list with all of the stops, you can define it using this function
     * @param array $stops
     */
    public function setStops( array $stops ){
        $this->stops = $stops;
    }

    /**
     * Get all of the stops, including the destination
     * @return array
     */
    public function getStops() {
        return array_merge($this->stops, array($this->destination));
    }

}

$obj = new EastBound();
$obj->setDestination(new Stop('Neverland', '6/16/2013 8:36:00 PM'));
$obj->addStop(new Stop('Radio City', '6/16/2013 8:28:00 PM'));
$obj->addStop(new Stop('Malt Shoppe Street', '6/16/2013 8:31:30 PM'));
$dest = $obj->getDestination();
echo "Final destination is ".$dest->getName(). ".\n";
var_dump($obj->getStops());

/**
 * Will return:
    Final destination is Neverland.
    array (size=3)
        0 =>
            object(Stop)[3]
                private 'name' => string 'Radio City' (length=10)
                private 'time' => string '6/16/2013 8:28:00 PM' (length=20)
        1 =>
            object(Stop)[4]
                private 'name' => string 'Malt Shoppe Street' (length=18)
                private 'time' => string '6/16/2013 8:31:30 PM' (length=20)
        2 =>
            object(Stop)[2]
                private 'name' => string 'Neverland' (length=9)
                private 'time' => string '6/16/2013 8:36:00 PM' (length=20)
 */

3 Comments

How is this "true oop"? Whether he is storing an array of strings, or an array of objects, he still needs to provide a member array container in order to house multiple entries. Granted, creating a stop object is more flexible for future feature enhancement, vs ending up with a monster multi-dimensional array.
This is one of the first things you would read in every decent OOP book for any object oriented language. You create objects that represent your data. Yes, in some cases you may be using arrays but it depends on the case and the data you're holding. In this case, he has a Stop which has more than one attribute. Thus it's a wiser idea to be using an object instead of plain old array
Again, my point, and the base question of the OP still stands. How do you access multiple, similar attributes of an object? Answer: Use a member array container, regardless of whether you are storing objects, strings, etc.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.