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

[eluser]J101[/eluser]
[quote author="OverZealous.com" date="1242030862"]What do you mean by "are the primary keys also joined"?[/quote]
What I mean is... If you have two tables that both have id columns, are these id colums joined?

users
id
firstname
lastname

addresss_users
id
table1_id
table2_id

addresss
id
address1
address2

If this were me, I would join these tables on the id columns. I know that I said 2 tables above but I figured I would provide a many2many relationship.


[quote author="OverZealous.com" date="1242030862"]DataMapper doesn't actually rely on any in-database relationship information, merely a properly configured and labeled database.[/quote]
This much I understand but there still needs to be a way to relate these tables so as to get the correct results back out.

[quote author="OverZealous.com" date="1242030862"]Also, please take a look at the original DataMapper examples, specifically the Getting Start and Database Schema sections.[/quote]
I've already looked at that documentation and its not very clear to me. I realize that stan left the project and that you picked it up but its kind of confusing having to reference two different manuals.
#72

[eluser]OverZealous[/eluser]
Yes it relates on ids. I don't understand why that is a question. As it says in the documentation, every table must have a primary key named id. What else would you join two tables on?

Your join table is wrong in your example. It should be:
Quote:address_users
id
address_id
user_id

This will be used to relate users to address. The id columns must all be automatically generated (autonum or serial, for example), as the existence of an id is what allows DM to determine whether to insert or update.

There really isn't two sets of documentation. I've taken the base DataMapper and added a few features. The only really important thing (regarding databases) that changed was that I allow 1-to-N relationships to use in-table relationships (In the example above, assume addresses can only have one user. Then you could include user_id on the addresses table directly.). If you don't use that or the more complex many-to-many relationships, just use DataMapper as it is.

I don't have time to update or rewrite the manual. I only offer DMZ as a benefit to the community, since many have asked for specific features (that I myself use).
#73

[eluser]J101[/eluser]
[quote author="OverZealous.com" date="1242032838"]Yes it relates on ids. I don't understand why that is a question.[/quote]
Well, I asked because the code I am looking at does not have any reference to id columns and it made me wonder why, that was why I asked.

[quote author="OverZealous.com" date="1242032838"]As it says in the documentation, every table must have a primary key named id. What else would you join two tables on?[/quote]
Exactly.

[quote author="OverZealous.com" date="1242032838"]Your join table is wrong in your example. It should be:
Quote:address_users
id
address_id
user_id
[/quote]
Actually, I made a mistake. I originally started to relate two tables called table1 and table2 but missed changing them later when I decided to make a M:M relationship.

[quote author="OverZealous.com" date="1242032838"]There really isn't two sets of documentation. I've taken the base DataMapper and added a few features. The only really important thing (regarding databases) that changed was that I allow 1-to-N relationships to use in-table relationships (In the example above, assume addresses can only have one user. Then you could include user_id on the addresses table directly.). If you don't use that or the more complex many-to-many relationships, just use DataMapper as it is.[/quote]
OK, this is good to know. Thanks. I was having a hard time sorting out what belonged to him and what you did. One thing that I see that you did was by allowing the 1-to-N relationships, you have cut way down on the number of tables that are needed and that's a good thing.

Thanks for the clairification! Smile
#74

[eluser]apersaud[/eluser]
Hi OverZealous,

I'd like to contribute some code that I've added to my DMZ 1.2.1 to make it easier working your objects as Arrays. I'm building an JSON based API for my website (Addicted2Salsa) and came across an issue.

Code:
//only an example of Addicted2Salsa episodes
$e = new Episode();
$e->get();
json_encode($e->all); //causes a recursion issue

What I added were simple methods to my Models so that I can convert them to arrays with only the fields I would like to make available.

Code:
//only an example of Addicted2Salsa episodes
$e = new Episode();
$e->get();
echo json_encode( $e->toArray() ); //this is OK.
This new toArray() will detect whether it is only 1 object or many. So it works on individual items given a $obj->all call.
Code:
//example 2 (a bit more complicated)
$cap = new Caption();
$cap->get();
$result = array();
foreach($cap-all as $c):
     $r = $c->toArray(); //knows it is just 1 item
     $r['extra'] = 'extra'; //add more fields
     $result[] = $r;
endforeach;

echo json_encode($result); //works properly

Since I've been adding it to most of my DMZ models (maybe because I haven't found a better way of doing it), I thought it would be a good idea to contribute it and let you take a look at it. I added a public toArray() which will convert the DMZ object to an Array given the column fields of the object. I have
Code:
/* In Episode class which extends DataMapper */
       /* $filter_fields will filter out the fields and making sure
       we don't expose those when creating our arrays */
     /* in this case, we will not expose id,created,updated and views fields */
      var $filter_fields = array('id', 'created','updated','views');
      
      // ... more methods here ...

       /* Main method */
    public function toArray(){
        
        if(count($this->all) < 2): /* if I'm a single item */
               return $this->_toArray(); /* call the private method */
        else:
                 /* Otherwise handle many */
                  $set = array();

                  foreach($this->all as $i):
                       $set[] = $i->_toArray();
                  endforeach;
            return $set;
        endif;
        
    }

       /* This method handles the single item case */
       /* Variable $filter_fields allows you to specify which
            column fields never to expose as array entries */
    private function _toArray(){
        
        $v = array();
        /* Get the column fields to expose given the ones
            we want to filter out by diff-ing the model columns and $filter_fields */
        $fields = array_diff( $this->fields , $this->filter_fields );
        foreach($fields as $f):
             $v[$f] = $this->$f;
        endforeach;
        return $v;  

    }

I think this might be useful to include some similar functionality in DMZ. These were my 2 cents. :-)
Let me know what you think.
#75

[eluser]OverZealous[/eluser]
That's an interesting method. I use a lot of JSON in my code, however, I have too many security restraints to allow objects to be written out in that manner (individual fields of an object may or may not be visible to a given user, for example).

I recommend that you look into creating an interim object for methods like this. Because they aren't specific to DataMapper's goals (which is connecting models to a database), they don't really belong in the core library.

How I handle this kind of code is to create an interim class (mine is called DataMapperExt). This class extends DataMapper, and then all of your models extend that.

The benefit is that you can easily add methods to all of your models without modifying DataMapper. If DM or DMZ gets updated, then you won't need to re-add in your changes.

Here's a starter class, along with a hint for usage:
Code:
// place in application/models/datamapperext.php
class DataMapperExt extends DataMapper {
    // standard PHP5 constructor
    function __construct() {
        parent::__construct();
    }
    
    // insert your custom methods here

}

// usage:
class User extends DataMapperExt {
    // required: PHP5 constructor.
    function __construct() {
        parent::__construct();
    }
    // use like normal
}

If everyone does this, then when someone decides to use your code, then they can just copy it into their extension model. It's more modular this way. I even have separate extension models for different purposes (ie: I have one that extends Ext to handle sortable models).

Alternatively, create a library or helper for your code. The function you describe might actually make more sense there, since it really is more generic. Most of my JSON code lives in helper functions.

PS: You definitely cannot use json_encode to print out a DataMapper object for any reason, even if ->all is empty. This is because each model includes references to many CI libraries, including DB and Load. You can imagine the mess that makes.
#76

[eluser]J101[/eluser]
I have datamapper set up but I am having a few issues with the method chaining. Can someone give me a hand. The following code produces the correct results but I need to manipulate the results before rendering them. What I would like to do is build a json array from the results. I believe that this should be done inside the controller and not the view. Let me say that I am new to CI as well as datamapper but not new to OOP. I figured that I would build the json array inside the controller method and then echo the results to the view.


Code:
$v = new Vehicle();
$v->where('owner_id',$user_id)->where('assigned_to_id !=',$user_id)->get();
$v->member->get();
$v->vin->get();
$v->employer->get();
$v->group->get();
$v->field->get();
$v->error->get();
$v->owner->get();
$v->assigned_to->get();
$v->status->get();
$v->other();

$data['vehicle'] = $v;

$this->view->load('content','vehicle/grid',$data);
$this->view->render();



foreach ...
my json array

Can someone please point me in the right direction?
#77

[eluser]OverZealous[/eluser]
You aren't clear as to what you want. All you have is a bunch of queries there, without specifying the output. And I don't see what issue you are having with method chaining (you use it just fine on the second line).

Also, those are all relationships? You only call get() on relationships, not on fields. Are any of those get()s $has_many relationships? Or are they all $has_one? What is other()?

You cannot use $error as a field name (or relationship). That is a reserved word. $field might give you trouble as well.

For all of your $has_one, if you are only trying to get the information for output, and you are using DMZ (which I assume you are), trying merging the columns you want into one query:
Code:
// change the values in the array to be the fields you want.
$v->join_related('member', array('name', 'field2', ...));
// repeat for each $has_one you want to join in.
// access the above using:
$v->member_name;
$v->member_field2;

As far as outputting a json object, you do something like this:
Code:
$output = array();
foreach($v->all as $value) {
    $item = array();
    $item['field'] = $value->field;
    ....
    $output[] = $item;
}

echo json_encode($output);

Although there may be more to it.

As far as putting it in the controller or view: that's personal preference. I decided to put my code in the controller, since 99% of it is gathering fields. I consider the json_encode() to be my "view". You should also set your Content-Type header to application/json.
Code:
header('Content-Type: application/json');

For debugging purposes (via Firebug), there's a good bit of code on the PHP json_encode page that handles pretty-printing the output. I then usually set the type to text/plain on my development server, so I can easily read the output.
#78

[eluser]J101[/eluser]
To start with, this isn't my code. I didn't write any of this and I'm trying to understand it myself.

Yes, I believe they all are relationships (and yes, there are a lot of $has_many in there also) because when I print_r $v, that is mostly what I am seeing are relationships and queries. What I don't understand is on the view side, they have
Code:
&lt;?php foreach ($vehicle->all as $v) { ?&gt;
<td>&lt;?php echo $p->member->sid; ?&gt;</td>...

and it is rendering the correct results but yet when I do the print_r on the controller side, I can't find any of the key/value pairs.

I am going to pass this info along to the other developer on this project and make him aware of it. He has more CI experience than I do and has coded most of what I am trying to understand.

I'll try what you suggested and be back to let you know what the output is.

Thanks!
#79

[eluser]OverZealous[/eluser]
Well, if you are calling print_r (which sometimes crashes PHP, due to recursive relationships) before the related items are retrieved, then they don't exist yet.

DataMapper uses __get to populate the related items as needed. This prevents it from loading in and processing unnecessary classes.

I don't understand the code you copied in (which could explain your confusion), either.

FYI: if you haven't yet, take a look at the (original) DataMapper documentation, specifically Getting Started and Accessing Relationships.
#80

[eluser]cube1893[/eluser]
Hi,

first of all, I want to say how happy I am with CI. RIight now, I want to migrate the code of my old project into the CI MVC-Framework. Everything worked fine but I'm experiencing a problem now:

I have a DB table for users, cars, bicycles and motorbikes. The tables cars, bicycles and motorbikes have a different data structure but an unique id. The user table has an id and a vehicle_id. Each user can either have a car or a bicycle or a motorbike.

In my old model, I stored a vehicle_type in the user table. If the vehicle_type equaled 1, then the vehicle_id has been linked to the car, vehicle_type 2 has been linked to bicycle etc.
I think it's not the best solution and as I'm changing the whole model and the data access (with DMZ) now, I want to change this.

Do you guys have any suggestions to solve this problem with the help of DMZ?

Thank you!




Theme © iAndrew 2016 - Forum software by © MyBB