在类中使用类外的foreach数组?

时间:2013-09-13 23:30:27

标签: php

我希望标题有意义,我正在学习使用PHP类,我很了解,我试图超越我读过/看过的教程并使用数组来返回值。

我纯粹只是在尝试并且好奇地知道我为什么做错了(我没有添加我的foreach尝试,希望有人可以指出在getTheGameType()方法上运行foreach的地方)和正确的方法去做吧。

//Just a manual array containing key/value pairs of games with their genres 
$array = array(
        "Grand Theft Auto" => "Action",
        "NBA 2k14" => "Sports",
        "COD" => "Shooting",
);

//My object
class videoGames {


    public $title;
    public $genere;

    public function setTheGameType($title,$genere) {

        $this->title = $title;
        $this->genere = $genere;
    }

    public function getTheGameType() {

            return 'The game genre for '.$this->title.' is:' . $this->genere;

    }

}

//New instance of `videoGames` class
$list = new videoGames();

//Here I set the game title with its genere
foreach ($array as $title => $genere) {
    $list-> setTheGameType($title,$genere);
}

//Echo the value passed into getTheGameType() function
    echo $list->getTheGameType();

以上返回COD的游戏类型是:射击获取阵列的最后一个值..

如何返回基本上循环getTheGameType()方法的所有键/值对?

修改 我通过将echo $list->getTheGameType();添加到foreach循环中来实现它。

方法问题?这是不好的做法吗?

   foreach ($array as $title => $genere) {
    $list-> setTheGameType($title,$genere);
    echo $list->getTheGameType();
}

4 个答案:

答案 0 :(得分:8)

在此示例中,您并未真正正确使用类。一个对象应该建模一个对象:

class VideoGame {          // Singular title (not gameS)

    private $title;        // Make these private - information hiding
    private $genre;        // spell this correctly!  :-)

    // Use a constructor to initialize fields in the class!
    public function __construct($title,$genre) {
        $this->title = $title;
        $this->genre = $genre;
    }

    // Here are "getters" for the two fields.
    // Note that I have not provided "setters" - so these fields will
    // always have their initial value (as set in the constructor).
    // Types like this (with no setters) are often called "immutable".
    public function getTitle() {
        return $this->title;
    }

    public function getGenre() {
        return $this->genre;
    }

    public function getDescriptiveString() {
        return $this->title . ' is a ' . $this->genre . ' game.\n';
    }

}

创建这些:

// This array has three instances of the VideoGame object.
// Often, this would actually be the result of a database query.
$game_array = array(
    new VideoGame("Grand Theft Auto", "Action"),
    new VideoGame("NBA 2k14", "Sports"),
    new VideoGame("COD", "Shooting")
);

迭代他们:

// We get the descriptive string from each game and print it.
foreach ($game_array as $game) {
    echo $game->getDescriptiveString();
}

另见:

答案 1 :(得分:2)

您正在实例化该类的单个实例并重写该类型。我假设你希望每个游戏都有自己的类实例:

$games = array();

//Here I set the game title with its genere
foreach ($array as $title => $genere) {
    //New instance of `videoGames` class
    $list = new videoGames();
    $list->setTheGameType($title,$genere);
    $games[] = $list;
}

foreach($games AS $game)
{
    echo $game->getTheGameType();
}

但是,请参阅jonathon关于课程架构的答案。这个答案只是为了说明你获得现在结果的原因。

答案 2 :(得分:2)

现在,您的videoGames课程名称确实没有正确命名。目前它只能存储一个视频游戏。当您运行循环时,您只是在对象上重置标题和流派的类属性。

如果你真的想在OOP工作,你可能需要两个课程,一个用于视频游戏,另一个用于代表一组视频游戏。所以,让我们假设您保持现有的课程,但重命名为video_game(单数)。

然后你可能想要添加一个类来存储这样的视频游戏:

class video_game_collection {
    protected $collection = array();

    // allow construction of collection by passing array of video_games (though not required)
    public __construct($game_array = null) {
        // validate all array elements are proper objects if the array is set
        if(is_array($game_array)) {
            foreach ($array as $game) {
                if ($game instanceof video_game === false) {
                    throw new Exception('You sent a date array element.');
                } else {
                    $this->collection[] = $game;
                }
            }
        }
    }

    public add_video_game($game) {
        if ($game instanceof video_game === false) {
            throw new Exception ('This is not a game.');
        }
        $this->collection[] = $game;
    }

    public get_collection() {
        return $this->collection;
    }
}

你可能不应该有这样的逻辑回应你的类内部的消息传递(将类限制为一个目的 - 表示数据对象)。所以我建议你只需在getGameType方法中返回游戏类型,而不是让它实际回显文本。将消息传递给课外的东西。

把它放在一起,你可以做类似

的事情
$collection = new video_game_collection();

//Just a manual array containing key/value pairs of games with their genres 
$array = array(
        "Grand Theft Auto" => "Action",
        "NBA 2k14" => "Sports",
        "COD" => "Shooting",
);

foreach($array as $game => $genre) {
    $game = new videoGame();
    $game->setTheGameType($game, $genre);
    $collection->add_video_game($game);
}

现在你有一个可以做反对的集合,比如返回所有标题,或者如果你构建添加的功能,按标题排序,返回特定类型的电影,返回所有类型等等。

答案 3 :(得分:1)

循环遍历数组,并在循环的每次迭代中成功地在对象中存储标题和流派。但是,您每次都会覆盖存储在对象中的值。当你运行$list->getTheGameType();时,你会看到你输入的最后一个值,因为它覆盖了以前的值。

如果您希望对象存储有关多个游戏的信息,请对其进行修改以将数据存储在嵌套数组中(甚至是代表单个游戏的新类对象)。如果您的类被设计为包含单个游戏,那么您将需要创建一个videoGames对象数组,在每个对象中存储有关一个游戏的信息。这都是关于如何建模数据的。