Part of the EllisLab Network
   
3 of 100
3
DataMapper 1.6.0
Posted: 18 September 2008 03:38 PM   [ Ignore ]   [ # 21 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  124
Joined  06-01-2008

Hi BaRzO.  The errors are set on the object itself, not the Controller, so all you need to do with your code example is replace $this with $u. Like so:

Replace:

echo $this->error->username;

With:

echo $u->error->username;

Alternatively, you can show all errors as a single string (each error within it will be wrapped by the error prefix and suffix tags):

echo $u->error->string;
// This might output something like:
//   <p>Username is taken.</p>
//   <p>Password must be at least 6 characters long.</p>

Looping through all errors:

foreach ($u->error->all as $error)
{
    
echo $error;
}

If you had instantiated your object like so:

$vehicle = new Vehicle();

You would access its errors like so:

echo $vehicle->error->property;

If you think I should update my User Guide to make this clearer, let me know.

 Signature 

[ DataMapper | DataMapper Source Files | DataMapper User Guide ] - [ History | History Source Files | History User Guide ]

Profile
 
 
Posted: 18 September 2008 04:09 PM   [ Ignore ]   [ # 22 ]  
Grad Student
Avatar
Rank
Total Posts:  78
Joined  02-13-2008
// Create User
$u = new User();
$u->username = 'Fred Smith';
$u->email = 'fred@smith.com';
$u->password = 'apples';
echo
'<br />';
echo
'<p>Current values:</p>';
echo
'<code><strong>ID</strong>: ' . $u->id . '<br />' .
'<strong>Username</strong>: ' . $u->username . '<br />' .
'<strong>Email</strong>: ' . $u->email . '<br />' .
'<strong>Password</strong>: ' . $u->password . '<br />' .
'<strong>Salt</strong>: ' . $u->salt . '</code>';
echo
'<hr />';        
echo
'<p>Now to save it to the database.</p>';
echo
'<code>
// Save User<br />
$u->save();</code>'
;
// Save User
if ($u->save())
{
echo '<br />';
echo
'<p>Current values:</p>';
echo
'<code><strong>ID</strong>: ' . $u->id . '<br />' .
'<strong>Username</strong>: ' . $u->username . '<br />' .
'<strong>Email</strong>: ' . $u->email . '<br />' .
'<strong>Password</strong>: ' . $u->password . '<br />' .
'<strong>Salt</strong>: ' . $u->salt . '</code>';
}
else
{
echo '<p><b>User has already been created</b></p>';
echo
$u->error->username; // Unable to access an error message corresponding to your field name.
// print_r($u->error->all);
}

i did it but is giving this result…

Unable to access an error message corresponding to your field name.

edit :
Your user guide is very good i did read it all..
but if you can put some more example would be very nice i think maybe for beginers like me smile

 Signature 

Sorry for my pour english :(

Profile
 
 
Posted: 18 September 2008 04:52 PM   [ Ignore ]   [ # 23 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  124
Joined  06-01-2008

Ah, I see.  I didn’t give an example of setting up the error messages for that, sorry.

What DataMapper is trying to do is read an error message for the “unique” validation rule from your validation language file.  One is not there by default since CodeIgniter’s Validation class doesn’t have the “unique” validation rule, DataMapper does, so it’s not finding it.

To solve this for now, copy the following into a file named validation_lang.php, and put it in your system/application/language/english folder.

<?php

// This is the new error message for the unique validation rule
$lang['unique']         = "The %s you supplied is already taken.";

$lang['required']         = "The %s field is required.";
$lang['isset']            = "The %s field must have a value.";
$lang['valid_email']    = "The %s field must contain a valid email address.";
$lang['valid_emails']     = "The %s field must contain all valid email addresses.";
$lang['valid_url']         = "The %s field must contain a valid URL.";
$lang['valid_ip']         = "The %s field must contain a valid IP.";
$lang['min_length']        = "The %s field must be at least %s characters in length.";
$lang['max_length']        = "The %s field can not exceed %s characters in length.";
$lang['exact_length']    = "The %s field must be exactly %s characters in length.";
$lang['alpha']            = "The %s field may only contain alphabetical characters.";
$lang['alpha_numeric']    = "The %s field may only contain alpha-numeric characters.";
$lang['alpha_dash']        = "The %s field may only contain alpha-numeric characters, underscores, and dashes.";
$lang['numeric']        = "The %s field must contain a number.";
$lang['integer']        = "The %s field must contain an integer.";
$lang['matches']        = "The %s field does not match the %s field.";


/* End of file validation_lang.php */
/* Location: ./system/application/language/english/validation_lang.php */

I’ll make an updated version of DataMapper that includes a language file with this sort of thing already set up for you, since it will need a similar message for the other inbuilt DataMapper validation rules.

For any custom rules you make in your models that extend DataMapper, you can use the error_message() function.

UPDATE

A language file has been included with version 1.2.1 that has the validation error messages for the DataMapper-only validation rules.

 Signature 

[ DataMapper | DataMapper Source Files | DataMapper User Guide ] - [ History | History Source Files | History User Guide ]

Profile
 
 
Posted: 18 September 2008 05:07 PM   [ Ignore ]   [ # 24 ]  
Grad Student
Avatar
Rank
Total Posts:  78
Joined  02-13-2008

Ok now it fixed smile
thanks i will try my self to learn what can i do with DM wink

Edit :
It’s me again smile
I want to ask… How we will drive with validation fields

$rules['username']    = "required";
$rules['password']    = "required";
$rules['passconf']    = "required";
$rules['email']        = "required";

$this->validation->set_rules($rules);

$fields['username']    = 'Username';
$fields['password']    = 'Password';
$fields['passconf']    = 'Password Confirmation';
$fields['email']    = 'Email Address';

$this->validation->set_fields($fields);
 Signature 

Sorry for my pour english :(

Profile
 
 
Posted: 20 September 2008 12:43 AM   [ Ignore ]   [ # 25 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  124
Joined  06-01-2008

Good question, and thanks for bringing it up since I think you’ve pointed out a shortcoming in the current version that I didn’t notice.

I’ve got the $rules side covered with the $validation array in the models, but I don’t think I covered off the $fields naming side of things for error messsages.  At the moment it uses the exact name of the field (username, email, etc) but as you’ve shown, sometimes you’ll want it like “Email Address” or “Password Confirmation” which is currently not accomodated.

It’ll require only a small change though, probably a change in format of the $validation array, or splitting it into a $rules and $fields array.  I’ll see what works best when I get the time, and then I’ll write up a full working “real world” example on how to use all aspects of the validation, including the naming of the fields for error messages etc.

 Signature 

[ DataMapper | DataMapper Source Files | DataMapper User Guide ] - [ History | History Source Files | History User Guide ]

Profile
 
 
Posted: 21 September 2008 08:49 PM   [ Ignore ]   [ # 26 ]  
Grad Student
Avatar
Rank
Total Posts:  31
Joined  09-21-2008

Hi,

Two quick questions about DataMapper:

1. Why do you use join tables for one-one and one-many relationships instead of just using foreign keys?

2. Can you search based on relationships? (ie: if you have a “restaurant” model, a “menu” model and a “menu_item” model, and restaurants have one menu and menus have many menu_items, can you find all restaurants that serve items with “chicken” in the name? Can you find all menu_items served at Joe’s Diner?)

Greg

Profile
 
 
Posted: 21 September 2008 11:44 PM   [ Ignore ]   [ # 27 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  124
Joined  06-01-2008

1:
I know I could have used foreign keys for One to One and One to Many relationships but my personal preference is to make it so the normal tables have no information at all about any other tables (including foreign keys).  So, they only contain the information relevant to themselves.  I also found doing it this way made the implementation of DataMapper much easier.

DataMapper ensures the integrity of relationships stored in joining tables are kept intact for each of the different relationship types, so you don’t need to worry about your One to One relationship becoming something else, it wont.

2:
Ok, so the Restaurant has a One to One relationship with Menu, and Menu has a One to Many relationship with MenuItem.

There’s several ways you can find which restaurants have the “chicken” dish.

NOTE: I’m assuming the “menuitems” table has a “dish” field, and the “restaurants” table has a “name” field.

Here’s one way (starting with the MenuItem):

// Dish to find
$dish = "chicken";

// Get the menu item the user wants
$menuitem = new MenuItem();
$menuitem->where('dish', $dish)->get();

// Loop through the menu's this dish is on
foreach ($menuitem->menu->all as $menu)
{
    
// Show the restaurants that the menu belongs to (that has the dish)
    
echo 'Restaurant ' . $menu->restaurant->name . ' has ' . $dish . '<br />';
}

Here’s another way (starting with all restaurants, to find the restaurants with the dish):

// Dish to find
$dish = "chicken";

// Get all restaurants
$restaurant = new Restaurant();
$restaurant->get();

// Loop through all restaurants
foreach ($restaurant->all as $r)
{
    
// Loop through all menu items in the restaurants menu
    
foreach ($r->menu->menuitem->all as $mi)
    
{
        
// If the meni item's dish is the same dish we're looking for
        
if ($mi->dish == $dish)
        
{
            
// Show the restaurant that has it
            
echo 'Restaurant ' . $r->name . ' has ' . $dish . '<br />';
        
}
    }
}

All MenuItems served at “Joe’s Diner”:

// Name of Restaurant
$name = "Joe's Diner";

$r = new Restaurant();
$r->where('name', $name)->get();

echo
'Restaurant ' . $r->name . ' has the following menu items:<br />';

foreach (
$r->menu->menuitems->all as $mi)
{
    
echo $r->dish . '<br />';
}
 Signature 

[ DataMapper | DataMapper Source Files | DataMapper User Guide ] - [ History | History Source Files | History User Guide ]

Profile
 
 
Posted: 22 September 2008 01:15 AM   [ Ignore ]   [ # 28 ]  
Lab Assistant
RankRank
Total Posts:  282
Joined  06-11-2007

From what i have read so far in the User Guide, i can see how powerful of a system this is.

I was however reading the section up on ‘Automated Timestamps’ and see at least one main problem with it.

The problem i see with it is that the ‘Created’ and ‘Updated’ fields have to be set ‘DateTime’ type, however when i am creating fields that hold dates i never store them that way i always have it as an integer field which stores the unix_time_stamp.

Is there a possibility of making it so that the automated timestamps can accept either of the 2?

Ray

Profile
 
 
Posted: 22 September 2008 02:23 AM   [ Ignore ]   [ # 29 ]  
Lab Assistant
Avatar
RankRank
Total Posts:  124
Joined  06-01-2008

Yep, that’s do-able although if you need unix style timestamps urgently, you can manage them manually.  I chose to use MySQL’s DateTime for the automated timestamps because it’s much more flexible.  I’ll make it a simple TRUE/FALSE setting as to which type gets used.

Just a bit of trivia, although a long way off the unix timestamp has a year 2038 problem.  Not really an issue though since most people will fix their systems before then wink

 Signature 

[ DataMapper | DataMapper Source Files | DataMapper User Guide ] - [ History | History Source Files | History User Guide ]

Profile
 
 
Posted: 22 September 2008 06:29 AM   [ Ignore ]   [ # 30 ]  
Grad Student
Avatar
Rank
Total Posts:  31
Joined  09-21-2008

In reply to the chicken dish and Joe’s Diner examples…

That’s perfect, the ability to chain models is very handy! That would make life much easier.

(ie: foreach($restaurant->menu->menu_item as $mi):)

It’d be sweet if you could do something like this:

$menuitem = new MenuItem();
$menuitem->where(‘dish’, ‘chicken’)->where(‘menu->restaurant’, “Joe’s Diner”->get();

instead of having to manually do a foreach loop.

Can use “assign” relations before issuing a save call?
Like this:

$restaurant->menu->menu_item = ‘Chicken’; (or $restaurant->menu->menu_item->add(‘Chicken’);
$restaurant->save();

Otherwise you’d have to do it like this right?
$restaurant->menu->menu_item->save($new_item); (having already created “$new_item” as a menu_item object

 

Also, can you delete like this?
$c->where(‘name’, ‘Australia’)->get()->delete();

 

As far as requiring join tables for one-one and one-many relationships… I don’t think it’s valid to say “it was easier to program that way”, becuase now it’s more work for someone using the library to create more tables. As for not wanting tables to know about each other (and therefore not having foreign keys), it’s an interesting way of looking at things. Are there any reasons you can see that would make that a desirable thing? I can’t really think of any major pros/cons either way off the top of my head. It’s something I certainly could get used to if I started using it.

One thing that could make life easier as far as managing lots of join tables is if you could manually set a join table name “prefix” (in database.php config file for example) so all join tables would appear together in an alphabetical list of table names (using “join_” or “_” for example).


Thanks,
Greg

Profile
 
 
   
3 of 100
3
 
Post Marker Legend
New Topic New posts Hot Topic Hot Topic with new posts New Poll New Poll Moved Topic Moved Topic Sticky Topic Sticky topic
Old Topic No new posts Hot Old Topic Hot Topic with no new posts Old Poll Old Poll Closed Topic Closed Topic Announcement Announcements
Theme
Change Theme
Visitor Statistics
The most visitors ever was 819, on March 11, 2010 10:15 AM
Total Registered Members: 119685 Total Logged-in Users: 39
Total Topics: 125882 Total Anonymous Users: 3
Total Replies: 662354 Total Guests: 398
Total Posts: 788236    
Members ( View Memberlist )