• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
DataMapper 1.6.0

Hi stensi,

First of all, great work! This makes my life so much easier when it does to managing data!

I have a problem though and its probably because im missing something obvious. I have 3 normal tables; courses, venues, categories and two joining tables categories_courses and courses_venues. Each course can have one venue and one category but the each category/venue can have many courses.

Im trying to create a list of courses by category and then venue, something like:


I thought i would be able to do it something like this :

$c = new Category();
$c->where('status', 0)->get();
foreach ($categories->all as $category)
    echo $category->name.'<br>';
    $v = new Venue();
    $v->where('status', 0)->get();
    foreach ($venues->all as $venue)
        echo $venue->name.'<br>';
        $cs = new Course();
        $v->where('status', 0)->where('venue', $venue->id)->where('category', $category->id)->get();
        foreach ($courses->all as $course)
         echo $course->name.'<br>';

But i cant get it to work!

Any help would be great!
Thanks in advance,

Thanks mintbridge :-)

Since you say that each Course can have one Venue as well as one Category, you can get to the Course directly from the Category if desired, rather than having to go through a Venue (but still being able to get a Course through a Venue). If this is not what you're wanting, you would of course remove the relationship between the Course and the Category, and just get to your Courses through the Venues.

Can you to make sure you have your models are setup like the the following, to fit in with what you've told me about the relationships between each of them? I've made the assumption that a Venue has one Category but a Category has many Venues.

Your Course model should have:
$has_one = array("venue" => "venues", "category" => "categories");

Your Venue model should have:
$has_many = array("course" => "courses");
$has_one = array("category" => "categories");

Your Category model should have:
$has_many = array("course" => "courses", "venue" => "venues");

Obviously if they have other relationships you'd include those as well.

Now, onto your code snippet. Here's how it should be done:

$status = 0;

// Get all categories with a particular status
$c = new Category();
$c->where('status', $status)->get();

// Loop through each category
foreach ($c->all as $category)
    echo $category->name . '<br />';

    // Get all venues related to the category, with a particular status
    $category->venue->where('status', $status)->get();

    // Loop through each related venue
    foreach ($category->venue->all as $venue)
        echo '&nbsp;&nbsp;' . $venue->name . '<br />';

        // Get all courses related to the venue, with a particular status
        $venue->course->where('status', $status)->get();

        // Loop through each related course
        foreach ($venue->course->all as $course)
            echo '&nbsp;&nbsp;&nbsp;&nbsp;' . $course->name . '<br />';

Stensi, thanks for your library.
But how can I set up linking the keys, if they are different from the "name of the table"_id?
And how can I set the table for relations many to many?

Your tables need to follow the rules set out in the Database Tables section of the DataMapper User Guide. If your tables do not follow the rules then unfortunately, DataMapper will not be able to map your tables.

As for setting up Many to Many relations, there are instructions in the Setting up Relationships section. Basically, the models that have a Many to Many relationship with each other would both have a $has_many setting corresponding to one another.

it would be good to have this opportunity to adjust.
because is not always possible, such restrictions.IMHO.

Thanks for this great library. I'm trying it right now and it's pretty cool Smile

It's maybe a stupid problem but I have boolean field in my table (a tinyint(1) called "is_published" where I store 1 or 0) and when I make a get() I can print 1 but not 0. The same thing appear when I want to update a row with "is_published" to 0, the field is not updated. Am I doing something wrong ?

EDIT : I try to explain better Tongue

Here's my model :
class Member extends DataMapper
  var $validation = array(
            'field' => 'firstname',
            'label' => 'Prénom',
            'rules' => array('required', 'trim', 'xss_clean', 'max_length'=>255)
            'field' => 'lastname',
            'label' => 'Nom',
            'rules' => array('required', 'trim', 'max_length'=>255)
            'field' => 'curriculum',
            'label' => 'Curriculum',
            'rules' => array('trim')
            'field' => 'is_published',
            'label' => 'Etat de publication',
            'rules' => array('required', 'numeric')

     * Constructor
     * Initialize DataMapper.
    function Member()

Here's my controller :
function edit ($id = '')
    $m = new Member();
    echo $m->is_published; // print 1
    if(count($_POST) > 0) {
      echo $this->input->post('input[is_published]'); // print 0
      foreach($this->input->post('input') as $key=>$val) {
        $m->{$key} = $val;
      echo $m->is_published.'<br />'; // print 0
      if ($m->save()) {
        echo $m->is_published.'<br />'; // print 0
Everything seems OK but if I look in my db, the field "is_published" is still at 1.

First, let me say this is a great script. For those of us who are new to data mapping, there's definitely a learning curve, but I'm quickly seeing how beneficial this can be. Could you explain a little about the validation? I understand it's linked to CI's Validation class, but I'm having a hard time figuring out how to retrieve errors. Say somebody doesn't enter a valid email. Well the script knows that it isn't valid, so it doesn't complete. However I don't see a way to grab the errors to see what's wrong. I already know how to validate fields myself, but I'm hoping there's a way I can tap into this script's automatic validation when attempting to save().

Thanks for the compliments.

One thing to take note of is one of the strange behaviours of PHP itself. For example, if you ran this code:

$one = TRUE;
$zero = FALSE;

echo "One: $one<br />";
echo "Zero: $zero<br />";

PHP would echo out:
One: 1

This is because a boolean value of FALSE (or 0) is not considered to be the actual number 0, so it will not echo 0. Strangely enough, TRUE will still echo 1. Try the above code and you'll see.

But, as you're not yet showing error messages, the Database value might be staying as 1 because it is not validating successfully and saving. To retrieve errors, there's a few different ways to do it.

// Create new Member
$m = new Member();

// Try to save the empty Member object
if ($m->save())
    echo 'Member saved successfully.  ID: ' . $m->id . '<br />';
    // 1. Echo all errors in the one string
    echo $m->error->string;

    // 2. Echo the error for each individual field
    echo $m->error->firstname . '<br />';
    echo $m->error->lastname . '<br />';
    echo $m->error->curriculum . '<br />';
    echo $m->error->is_published . '<br />';

    // 3. Loop through the error array and echo each error
    foreach ($m->error->all as $e)
        echo $e . '<br />';

If you modify your edit method to show the errors, you should be able to see why it's not updating in the Database. Use whichever way you'd prefer.

For more information on using Error Messages, read the Validation section of the DataMapper User Guide (the part on Error Messages is towards the end of that section).

Good luck!

Looks like I answered both questions in one go Wink

Wow dude, you rock! This is really looking very usable to me now - after these few changes.

Making the join tables use the model's name is perfect!

[quote author="stensi" date="1222741788"]I'll just make DataMapper use CodeIgniter's Inflector helper for automatically figuring out ALL of the singular/plural work.

It's smart enough to know that "Countries" is the plural of "Country" but unfortunately it's not smart enough to know "People" is the plural of "Person", and in those cases, this one particularly, you'd have to have "Person" as your Model and "Persons" as your Table.[/quote]

Could you make it an optional parameter somehow? So it'll use the inflector unless you give it a plural to use?


Version 1.3.1 has been released!

View the Change Log to see what's changed.

In short, the self referencing relationships are now fully supported. I've included a complete example showing how it's done, with some useful code gems amongst it.

I've chosen not to go ahead with making CodeIgniter's Inflector Helper automatically do all the singular/plural work, so things remain as normal in that regard (that is, it uses the Inflector Helper to figure out the table name only if you haven't specified it, rather than it always figuring it out and ignoring your setting).

I've included my improved version of the Inflector Helper, which handles a greater number of irregular nouns, to make the automated table naming better.

I also made a mention of you in the Credits Greg, since you've been a great source of ideas and strong driving force in getting me to make DataMapper what it is now. So thanks :-)

Thanks to everyone else who've suggested things as well!

Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  

  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.