Okay! It was a problem with the reserved names. I’ve implemented a networked tree and I’m keeping track of parents by calling the field parent. Name changed, problem solved. Thanks a lot.
This is an archived forum and the content is probably no longer relevant, but is provided here for posterity.
The active forums are here.
September 05, 2008 12:32pm
Subscribe [115]#706 / Apr 17, 2009 2:29am
Okay! It was a problem with the reserved names. I’ve implemented a networked tree and I’m keeping track of parents by calling the field parent. Name changed, problem solved. Thanks a lot.
#707 / Apr 17, 2009 1:49pm
@Phil
You have two options. Either continue with what you had been doing (and that’s fine, and it’s the fastest solution), or write a custom _related rule. There’s a section on that in the docs. I’m not sure you would be able to get that to work, though, because both fields wouldn’t be set at the same time.
So, I guess I would recommend using the previous method and sticking with the unique_pair.
I wonder if it would be worth adding “custom_field_validation” and “custom_related_validation” methods to DMZ that runs after all of the other rules are run, for complicated validation that needs to happen after everything else has been checked, but before saving or committing a transaction.
Thanks for the guideance so far. I am comfortable with what I’ve done so far, but I in way I don’t want to lose sight of what DMZ/DataMapper functionality may be able to improve on.
Well, you mentioned a possible keyword “TRANSACTION.”
Since I use the InnoDB engine, I will try and utilize that approach of Datamapper (CodeIgniter)
Basically, it should save having to attempt a custom validation rule, especially since the validation would be based on the INDEX and not the columns.
I wouldn’t pull any hairs on modifying DMZ just yet though, this functionality may have a solution as it stands.
Thanks again Phil…
-bEz
p.s. - FOREIGN KEYS, can you provide a brief summary why FOREIGN KEYS are not used (supported, required, etc.) with DataMapper/DMZ?
#708 / Apr 18, 2009 12:11am
Been pulling my hair a while, pondering why I could log in without supplying proper credentials, even following the user guide example.
Line 451 <datamapper.php>, “$data = $this->_to_array(TRUE);”, why is this flag set to TRUE? Consider the following code:
$user = new User();
$user->username = $this->input->post('username');
$user->password = $this->input->post('password');
$user->validate()->get();
if ( ! empty($user->username)) /* authenticated stuff */With flag set to TRUE the post-validation fetching becomes:
$user->where('username', $this->username)->get() (effectively logging the visitor in without needing a password)
With flag set to FALSE:
$user->where('username', $this->username)->where('password', $this->password)->get()… or have I missed something obvious in my 5 AM coding spree?
#709 / Apr 18, 2009 12:36am
@bEz
I’m not the original author, but the basic reason foreign keys are not used is that they provide no benefit. There’s no way to get feedback about foreign keys from the database in a consistent way. The server still has to check on those restrictions by hand.
If you want to use foreign keys, you can, but I have a feeling that they might cause errors. That being said, some databases use foreign keys to speed up queries, so just adding in the reference (without any other restrictions) might work.
@Burgestrand
That call is important, otherwise the query would include every empty or null field on the table in the query, and probably never return a result. If you look at _to_array(), it’s easy to see what that flag means.
You are actually doing it wrong, if the copied code is correct. Look at the example again. Notice that the user is looked up by email first, then the email and salt is copied over to a new account. That account has the password validated, and then the validate/get is run.
Also, I think you might not have required on your password field, which is why the validation routine succeeds on an empty password. If someone is able to log in with an empty password, that failure is most likely at the validation(), not the get().
#710 / Apr 18, 2009 1:10am
The login method actually looks like this:
$user = new User();
$user->where('username', $this->username)->get();
$this->salt = $user->salt;
$this->validate();
var_dump($this->password, $this->error->string);
$this->get();
return ! empty($this->username);I’m dumping the data to find wherever my error is located, with the following result:
bool(false) string(392) “
The Username field is required.
The Username field must be at least 1 characters in length.
The Password field is required.
The Password field must be at least 6 characters in length.
The E-Mail field is required.
The E-Mail field must be at least 5 characters in length.
“
I believe the problem is in the validation condition checking. Line 444(still datamapper.php), “if ($this->validated)” — sure, it has been validated but it was found not valid, and I can’t find any check to make sure it has been before fetching the new data.
I’ll go to sleep and look at this in the morning, I think it’s needed. ¬¬
#711 / Apr 18, 2009 1:30am
I finally dug through my code (it’s been a long while since I wrote that section), and I realized that I am actually hand checking to ensure that the fields are not empty, before I even call ->validate(). (I think I wanted a better error than the generic required error.)
In other words, you are absolutely correct. DataMapper does not handle ->validate()->get() correctly, because even if it is invalid, it still queries.
I might correct it on my version (DMZ), but for now I recommend just checking to ensure that the fields are not empty first. Alternatively, check $user->validate()->valid first and run the errors or then do the get() if it was valid.
#712 / Apr 18, 2009 7:25am
Hi, I’ve just started using DataMapper and I’ve probably overlooked or forgotten something, but as a quick test I ran the following code, expecting it to output all the users’ emails.
$u = new User();
foreach ($u->get()->all as $user)
{
echo $user->email . '<br>';
}Instead I only get the email of the last user in the table. What have I done wrong?
#713 / Apr 18, 2009 8:04am
Could you post the code from your model, and the structure of the users table
#714 / Apr 18, 2009 9:19am
Table users structure is :
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| username | varchar(255) | NO | | NULL | |
| f_name | varchar(255) | NO | | NULL | |
| l_name | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | | NULL | |
+----------+--------------+------+-----+---------+----------------+Model code is :
class User extends DataMapper {
function User()
{
parent::DataMapper();
}
function test() {
$u = new User();
foreach ($u->get()->all as $user)
{
echo $user->email . '<br>';
}
}
}#715 / Apr 18, 2009 1:14pm
I know what’s wrong. Your ID is uppercase, it needs to be “id”. [Update: on the table.] The reason this matters is that DataMapper uses the ID as the index for multiple item results. Since “id” is being returned as “” (empty string), all of the users are being stored at the same index, overwriting each other.
#716 / Apr 19, 2009 2:45pm
Hello!
Im new in DataMapper and I have some probleme:
When my table is empty, I can save a new product this way:
function add(){
$p = new Product();
$p->status=$this->input->post("status");
$p->brand=$this->input->post("brand");
$p->name=$this->input->post("name");
$p->note=$this->input->post("note");
$p->url=url_title(strtolower($this->input->post('name')), 'underscore');
if ($p->save()){
echo "ok";
}else{
echo $p->error->string;
}
}But second time when I save an other product with different data, first row duplicates in the database instead of a new insert with product2 data. I dont understand..
id: 1
name: product1
brand: Nike
(..)
id: 2
name: product1 (instead of product2)
brand: Nike (instead of Adidas)
(..)Whats wrong with my code?
Peter
#717 / Apr 19, 2009 3:35pm
There’s nothing that DataMapper is doing that could cause this. You are either inputting the same data, or your database has problems.
Turn on CodeIgniter’s profiling (it’s in the docs), and see what the query is. Use that to do some debugging.
<rant>
This isn’t directed at any one person in particular, it’s a general complaint 😉
I don’t understand why developers have a problem, and then don’t even try some basic debugging. It doesn’t take that much time, and it’s not like someone can look at the code above and see if something is wrong.
Please take some time to do basic debugging. Look at your queries, echo() input variables, take some time to look over the documentation, and compare your code with example code. It helps reduce the number of “I did X. It didn’t work. Help!” posts, which are almost always mistakes in custom code, not in the libraries.
As you can tell by looking through this thread, I don’t have a problem helping people, and I do my best to ensure that problems are fixed (when I can, since DM isn’t written or managed by me).
</rant>
#718 / Apr 19, 2009 7:26pm
Hello Guys!
this is amazing ! , very thanks stensi. First, sorry for my english.
I have problems with the join of tables.
My data model :
class Costumer extends DataMapper {
$table = 'costumers';
var $has_many = array('invoice','receipt');
}
class Invioce extends DataMapper {
$table = 'invoices';
var $has_one = array('costumer');
var $validation = array(
array(
'field' => 'date',
'label' => 'Invoice date',
'rules' => array('valid_date','required')
),
array(
'field' => 'total',
'label' => 'Invoice total',
'rules' => array('required')
)
);
}
class Receipt extends DataMapper {
$table = 'receipts';
var $has_one = array('costumer');
var $validation = array(
array(
'field' => 'date',
'label' => 'Receipts date',
'rules' => array('valid_date','required')
),
array(
'field' => 'total',
'label' => 'Receipts total',
'rules' => array('required')
)
);
}When i use my costumer model , i have 2 records set or objects set =):
$costumer->invoice and $costumer->receipts , but i need make a report like this :
from costumer id : 1
date (from receipts or invoices) invoice sum receipt sum
2008-03-20 200 u$s
2008-02-22 150 u$s
2008-02-23 150 u$s
2008-02-23 100 u$s
when using native sql query i created a table with union and ordered by date. Received a set of records and printed without any problems. How can I do this using datamapper?
Very thanks for the work. Congraturations =)
Ale.
Web development
#719 / Apr 19, 2009 8:27pm
DataMapper does not provide the means to do what you ask. I recommend loading in all of the invoices and receipts that you want, and then sorting them in PHP.
It shouldn’t take too long to sort those records, especially if each group is pre-sorted by date.
Pseudo-code:
$invoices = ... // load in your invoices
$receipts = ... // load in your receipts
$list = array_merge($invoices->all, $receipts->all);
usort($list, "sort_on_date");
// $list now contains a sorted list
// in a helper
function sort_on_date($a, $b) {
// you may need to replace this with a different function if your dates aren't YYYY-MM-DD strings
return strcmp($a->date, $b->date);
}I forgot to mention that you can check to see what type an object is by using $object->model, which should be “invoice” or “receipt”.
#720 / Apr 20, 2009 11:47pm
A couple DataMapper questions:
Is there a standard method for importing form fields from $_POST into a DataMapper object, aside from a bunch of $this->fieldname = $CI->input->post(‘fieldname’) lines?
Is there a way to distinguish a form validation error from a database or other system error in the save() method?
Thanks for all your help,
Jack