Welcome Guest, Not a member yet? Register   Sign In
[Deprecated] DMZ 1.5.3 (DataMapper OverZealous Edition)

[eluser]mcnux[/eluser]
Wow, that was quick!

$userTwo is an existing user (the example in my first post was typed to keep it simple and I miss-typed it. I think I was checking to see if the save() returned true in my actual code but I am not sure now. I will have another look a little later and let you know how I get on.

Thanks.

[eluser]mrtavo[/eluser]
[quote author="OverZealous.com" date="1247528895"]After apparently enough caffeine has gotten into my system, I finally found out that the problem IS within DataMapper / DMZ, and, yes, it can be fixed.

Here's the temporary solution: search for and replace 'left' with 'left outer' in the libraries/datamapper.php file.

I'm planning on implementing this anyway, as that is more appropriate syntax (they are synonymous with each other). It should be fully supported across all databases, since LEFT OUTER JOIN is the correct SQL term.[/quote]

Sorry, but I am still having problems with this.

I changed 'left' with 'left outer' in the library, but I still have problems. Here is another attempt that I made.

Code:
$query = "
   select Bs.*
          from Bs
          left outer join As as As
          ON Bs.id = As.Bs_id
          WHERE As.id = '10'
   ";
   echo $query.'</br>';
   $r = $this->db->query($query);
   $r = $r->first_row();
   echo '<pre>'.print_r($r).'</pre>';
   echo 'With DMZ</br>';
   /* $e is a valid A object with id = '10' ( $e->get_where(array('id'=>'10')); ) */
   $u->where_related($e)->get();
   foreach($u->all as $c) echo $c->name.'</br>';
   /* trying $u->all to see if returns more than 1 (what is an error) */
   echo 'End DMZ</br>';

The result is this.


select Bs.*
from Bs
left outer join As as As /* the real name is not As so this is not a problem */
ON Bs.id = As.Bs_id
WHERE As.id = '10'

stdClass Object ( [Bs.id] => 1 [Bs.name] => XX [Bs.description] => XX )

1

(gives an object that is the true result)

Con DMZ
A Database Error Occurred

Error Number: 1

SQL logic error or missing database

SELECT Bs.* FROM (Bs) LEFT OUTER JOIN As as As ON Bs.id = As.Bs_id WHERE As.id = '10'


The difference between both querys are those parenthesis around "From '('Bs')'", using CI db object and that query gives the same error.

Could those parenthesis be the problem ? ( so estrange )

Looking to the sqlite documentation "sqlite Language: Select", at the "single source" statement seems to be correct.

So, I don't know what to do, it seems that finally I'm doing something wrong.

I'll keep on trying

**UPDATE: 'left' and 'left outer' are equivalent in sqlite too, I've done another try with the same querys with 'left' instead of 'left outer' and the result is the same, so that is not the problem.

Sorry for being so heavy and noob Sad

[eluser]mcnux[/eluser]
[quote author="OverZealous.com" date="1247580725"]@mcnux
• Have you checked to see if you are getting a TRUE result from your save? I see this a lot, and it is 100% wrong:
Code:
$userTwo->save($userOne->client->get()->all);

It should always be encapsulated in an if statement:
Code:
if($userTwo->save($userOne->client->get()->all)) {
    // success
} else {
    show_error('Error Saving: ' . $userTwo->error->string);
}

Otherwise, you don't know that there wasn't a validation error. Note: error->string may still be empty, if your models are mis-configured.
[/quote]

It was returning false but error->string was empty. I delved further in but could not see any related logging information which would help, even when set to log everything? So I had a look through the datamapper->_save_relation() method and found my error; when $object->save() is called (line 2871) it fails because of my "user required" validation rule on the client model:

Code:
var $validation = array(
  'user'=>array(
    'label'=>'User',
    'rules'=>array('required')
  )
);

I have a couple of problems with this.

1) I don't understand why the validation failed - the relationship was essentially set on line 2870? If I replace the contents of the else if block with return $object->save($this) it works as expected, but I imagine this isn't going to work in all cases? I stopped looking at this point as I am either doing something very wrong or this is a bug.

2) Should the errors from the relation saving not cascade back up to the object I was originally saving ($user in this case) so that I can use the if-else block as you suggested? Otherwise, how can I sanely check for errors when saving relationships? Or I have not configured my model correctly? I don't recall seeing anything on this in the documentation.

Hope that all makes sense. Please advise. Let me know if you require code examples.

[eluser]Daniel H[/eluser]
Hi Phil,

Going back to an earlier problem with the required validation, I have another example where required objects are simply not validating correctly at all.

Objects:

A claim has one website, one user, one directory_entry and one role.

Claim model

Code:
class Claim extends DataMapper {

    var $has_one = array('user', 'directory_entry', 'website', 'role');
    
    var $validation = array(
                                'user'=>array(
                                    'label'=>'User',
                                    'rules'=>array()
                                ),
                                'directory_entry'=>array(
                                    'label'=>'Directory Entry',
                                    'rules'=>array('required')
                                ),
                                'website'=>array(
                                    'label'=>'Website',
                                    'rules'=>array()
                                ),
                                'role'=>array(
                                    'label'=>'Role',
                                    'rules'=>array('required')
                                )
    );

Directory entry [snippet]:

Code:
class Directory_Entry extends DataMapper {

    var $has_many = array('user', 'claim', 'post');


Website [snippet]:

Code:
class Website extends DataMapper {

    var $has_one = array('user', 'screengrab');
    var $has_many = array('category', 'post', 'view', 'collection', 'comment', 'claim');

Role [snippet]:

Code:
class Role extends DataMapper {

    var $has_many = array('claim');

Now when I run the following after having got all the objects successfully...

Code:
if ($claim->save(array($entry, $user, $website, $role)))

...I get: The Directory Entry relationship is required. This occasionally can be an error related to the Role relationship being required (I don't understand what conditions the other error is shown). However in the database, the claim record is actually saved despite having 'failed' the validation, with the directory_entry_id populated, but all the other id's NULLed.

Other notes:

- If I remove the four required validation rules from claim the record is saved successfully and perfectly. This means that all the objects (fetched using get_by_id are being retrieved from the db successfully and are correct, so this is definitely not the issue).
- All my relationship ID fields on the claim table are NULLable.
- Caching is turned off in the constructor of this controller. Caching has caused some issues before, but none of these queries are being cached.

Does it seems that save() can't handle more than one or two objects at one time?

Any ideas? I can't see where I'm going wrong at all.

Tested on 1.3.3 and 1.3.2.


Update... these are the last few bunch of SQL statements from the profiler. Looks like it is counting rows in claims against a NULL id for each other objects? Is that supposed to happen?

Code:
0.0002       INSERT INTO `claims` (`role_other`, `notes`, `approved`, `date_created`, `date_updated`) VALUES ('', '', 1, 1247612835, 1247612835)
0.0002       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `user_id` IS NULL
0.0001       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `directory_entry_id` IS NULL
0.0001       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `website_id` IS NULL
0.0001       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `role_id` IS NULL
0.0002       UPDATE `claims` SET `directory_entry_id` = '9' WHERE `id` = 69
0.0001       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `user_id` IS NULL
0.0002       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `directory_entry_id` IS NULL
0.0001       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `website_id` IS NULL
0.0001       SELECT COUNT(*) AS `numrows`
FROM (`claims`)
WHERE `role_id` IS NULL

[eluser]OverZealous[/eluser]
@mrtavo

Well, my guess is it is an issue between sqlite and CodeIgniter, as DataMapper doesn't write any raw SQL code, nor does it have any control over the output.

DataMapper does not really support dynamically created databases, so I am unable to provide further help for this problem at this time.

Please let me know if you discover a solution!


@mcnux
If the result of the save returns FALSE, this means one of two things:

1) The validation failed. This should always show an error unless you are using custom validation code.

2) The saving of a related object failed. There are a few common reasons for this:
• First, the related object being saved is not saved.
• Second, the object itself isn't saved (but this shouldn't ever happen).
• Third, the most often case, your relationship properties are not correctly configured. Please see the FAQs

To help alleviate this in the future, I'm adding code to DMZ 1.4 that will create error messages when a related save fails. For now, please carefully check your relationship configuration, and make sure that you do not have any typos on either side of the relationship.


@Daniel H
Those SELECT * FROM {table} WHERE {field}_id IS NULL queries are bugs. I found them recently during my testing, and have them fixed in the next release of DMZ (which is now 1.4.0). I didn't realize that it was also affecting the 'related_required' rules until you pointed it out.


The 1.4 release has a lot of fixes and improvements, but I'm still testing the new version. The goal is to have a completely functional test site that I can use to verify changes against. I probably won't have the updated version out until later this week, as creating a test bed is taking far longer than I originally estimated.

[eluser]mcnux[/eluser]
Quote:@mcnux
If the result of the save returns FALSE, this means one of two things:

1) The validation failed. This should always show an error unless you are using custom validation code.

2) The saving of a related object failed. There are a few common reasons for this:
• First, the related object being saved is not saved.
• Second, the object itself isn’t saved (but this shouldn’t ever happen).
• Third, the most often case, your relationship properties are not correctly configured. Please see the FAQs

To help alleviate this in the future, I’m adding code to DMZ 1.4 that will create error messages when a related save fails. For now, please carefully check your relationship configuration, and make sure that you do not have any typos on either side of the relationship.
Sorry I probably wasn't very clear in my previous post. The validation of the related object (client - there was only one) failed when saving the relationship on the user ($userTwo->save($userOne->client->get()->all)). I couldn't see the error message on $userTwo - I think you got this bit as you mentioned DMZ 1.4 fix.

The actual error was issued because my validation rule requires that a client has a related user. I don't understand why this rule failed, my relationship configuration must be ok as I can relate a bunch of clients who aren't currently assigned to another user to $userTwo, it only fails when they are already assigned to another user. The save works fine when I remove the user validation rule from the client model.

I am happy to avoid adding validation to relationships to get around this but thought you may want to have a look into it.

Many thanks for your help. Great job.

[eluser]freshface[/eluser]
I am looking into DMZ before using it in projects, but still have some questions.
The original version of Stensi, is it still in development? Or is DMZ the latest one?

How would DMZ handle this:

1.
I have a blog module in my backend and want to generate a slug from my blog title (Hello ç World would become => hello-world)
And if the slug hello-world exists it should become hello-world-1, and of hello-world-1 exists it becomes hello-world-2, and so on…

How would the DMZ approach be? Do I use a custom validation with ci active record syntax?

2. When i have a one_to_many relationship and i want to display the 'name' field from table 1 and 2 (both tables have a name field) how does DMZ handles this

Code:
$u = new User();
$u->get();

echo $u->name; and echo $u->???;


3. The validaion DMZ comes with, does this replaces form validation? Or it is just a helper to work strict?
If you use form validation + validation in DMZ you write double code.

Regards

[eluser]OverZealous[/eluser]
@freshface
The original DataMapper is not currently in active development. Stensi has been very busy, and unable to update it since the last release in December 2008. DMZ is a significantly enhanced version of DataMapper, containing a lot of new features.

1) DataMapper is used exclusively for mapping database tables to objects, so this is unrelated to DMZ. How you handle it is up to you. I would recommend having an extra column that stores the ‘slug’, and then you can easily query on it.

2) You don't look up data the way you are thinking. A $has_one relationship works the same as a $has_many relationship. In other words, you will usually look up the second object like this:
Code:
// other_object is your $has_one related model
$u->other_object->get();
echo $u->other_object->name;

With DMZ there is an alternate method, include_related('other_object'). If you use this, then you only need one query (really important if you are looping over results), and you access related object fields as $u->other_object_name.

3) Validation is handled completely automatically with DataMapper. Please look at the documentation. The recommended method for processing an object is something like this:
Code:
function edit($id, $save = '') {
    $u = new User();
    $u->get_by_id($id);
    if( ! empty($save)) {
        // attempt to save data
        $u->name = $this->input->post('name');
        if($u->save()) {
            // save was OK, redirect or render output
            return;
        }
        // Otherwise fall through and re-render the editing view.
        // This also preserves any fields input by the user.
    }
    
    $data = array('user' => $u);
    $this->load->view('user_edit', $data);
}

Your view can output errors if they exist within $user->error.

Please take some time to look through the very thorough documentation.

[eluser]PoetaWD[/eluser]
[quote author="freshface" date="1247713124"]I am looking into DMZ before using it in projects, but still have some questions.
The original version of Stensi, is it still in development? Or is DMZ the latest one?

How would DMZ handle this:

1.
I have a blog module in my backend and want to generate a slug from my blog title (Hello ç World would become => hello-world)
And if the slug hello-world exists it should become hello-world-1, and of hello-world-1 exists it becomes hello-world-2, and so on…

How would the DMZ approach be? Do I use a custom validation with ci active record syntax?

2. When i have a one_to_many relationship and i want to display the 'name' field from table 1 and 2 (both tables have a name field) how does DMZ handles this

Code:
$u = new User();
$u->get();

echo $u->name; and echo $u->???;


3. The validaion DMZ comes with, does this replaces form validation? Or it is just a helper to work strict?
If you use form validation + validation in DMZ you write double code.

Regards[/quote]

Using DMZ is the BEST thing you could ever do !

I dont know what I would be without it !

Wink

[eluser]jpi[/eluser]
Hi,
First of all, thanks for this library, it's very powerful. You and Stensi made a great work.

I have a little request regarding the way the form_validation from CI is loaded in DMZ. I think it should be loaded in the validation method and not in the contructor (i mean in _assign library which is called in the constructor). For two reasons :
1) I don't use DMZ validation capacity, so i don't expect this library to load another library to validate my input.

2) But the main reason is for international application. Let me explain : in my controller I set the language of my app (by doing something like $this->config->set_item('language', 'french')) This is done after that auto_loaded library (such as datamapper) is loaded. But since datamapper loads form_validation at startup and form_validation loads form_validation_lang, the language I have manually set has no effect (indeed once form_validation_lang is loaded it cannot be loaded another time even if the language has changed).

I have solved my issue with a little hack like this in my controller
Code:
$array_index = array_search('form_validation_lang.php', $this->lang->is_loaded);
    if ($array_index !== FALSE && is_int($array_index)) {
      unset($this->lang->is_loaded[$array_index]);
    }
    $this->lang->load('form_validation');
(This force to reload form_validation_lang)

Have you understood my point (i am not an english speaking person so maybe I am not clear enough). Do you think it's possible to load CI form_validation in the method validate of DMZ ? (i don't see any side-effect in the DMZ code).

Thanks !




Theme © iAndrew 2016 - Forum software by © MyBB