0

I am a bit lot about what to do in an OO/DB relation...

Here is the DB model :

CREATE TABLE User
    Id

CREATE TABLE Location
    userId
    // EDIT oups, wrong !
    // placeId
    // Should be :
    seatId

CREATE TABLE Game
    locationId

Now some code :

class User
{
    private Location locations[]; // need this for several reasons...

    public function loadFromDatabase()
    {
        // Load data from DB
        // ...
        result = DB::query("SELECT Id FROM Locations WHERE userId="+this->Id);
        foreach(result)
        {
            l = new Location();
            l->loadFromDatabase(result);
            locations[] = l;
        }
    }    
}

class Location
{
    private User user;
    public function loadFromDatabase()
    {
        ...
    }
}

class Game
{
    private Location location;
    public loadFromDatabase()
    {
        /*
        Here comes the problem : 
        how to have a reference to a location 
        created by the User class ?
        */
    }
}

A User play Games in several Locations. EDIT : And for each location the user plays on seat. Or on another seat... When I want to know where a game has been played I access Game.location. And when I want to know who played it, I access Game.location.user

Here is my problem : I want the Game.location to be the same reference to one of the User.locations and I do not know how to do this... And, globally, I feel something wrong about my code...

Any help ? Thanks

Antoine
  • 480
  • 1
  • 4
  • 15

1 Answers1

1

Since you have a placeId in your Location table, I assume there is a Place table which describes what the places actually are, while the Location table simply represents the many-to-many mapping between users and places.

In that case, Location doesn't need to have an Id of its own and doesn't need to be a class, but Place does.

To load just one instance of each object from the database, cache the instances in a static map inside each class.

class Place
{
    // Static
    private static Place loadedPlaces[];

    public static function get(id)
    {
        if (!loadedPlaces[id])
        {
            loadedPlaces[id] = new Place(id);
            loadedPlaces[id]->loadFromDatabase();
        }
        return loadedPlaces[id];
    }

    // Non-static
    private id;

    public function loadFromDatabase()
    {
        // ...
    }
}

Then to get references to places for the properties of a user or a game, you just access them via the static method.

class User
{
    public function loadFromDatabase()
    {
        result = DB::query("SELECT placeId FROM Locations WHERE userId="+this->Id);
        foreach(result)
        {
            places[] = Place::get(result);
        }
    }    
}

class Game
{
    public function loadFromDatabase()
    {
        place = Place::get(place);
    }
}

This uses:

aaz
  • 5,136
  • 22
  • 18
  • 1
    Thank you for your answer. You gave me what I needed. I did not give some details and I did not write correctly my classes names. Instead of placeId, you should read seatId. A user may play a game in a location on one reserved seat, and play in the same location on another reserved seat. But, what you explained about the static map is exactly what I needed : in that way I can save unique instances. BTW, is there any design pattern according to this way ? – Antoine Feb 07 '11 at 17:36
  • Added some links. Regarding the game/location relation, it sounds like it's one-to-one, so maybe there's no need to separate the two. Instead you could have a table with a `game_id`, `user_id` and `place_number` to relate games to users and their place numbers and have a (fixed-size?) array in the `Game` object linking to users. – aaz Feb 07 '11 at 20:21
  • Thank you for the links, that's exactly what I needed. Most of the time I have solutions to my problems but I am never sure they are "well coded". That is why I love to write code based on design patterns. And your explanations + links do the job ! – Antoine Feb 08 '11 at 09:45