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

[eluser]OverZealous[/eluser]
[quote author="PoetaWD" date="1248831535"]Is there a way to get a single random object ?[/quote]

Yes, if your database sorts ORDER BY RANDOM. Please check the manual, under the Get page, with the Order By function. The basic idea is something like:
Code:
$object->order_by(id, "random")->get(1);

[eluser]OverZealous[/eluser]
[quote author="Jack Scott" date="1248835689"]Is there a simple way to detect whether a database field has changed in DMZ?[/quote]

All fields are NULL until they are set on a new object. You might be able to simply use is_null($object->{$field}).

However, if you need nulls, this won't help.

For already-saved objects, as long as the object remains in memory while both sources are read, you should be able to use the built-in $stored object. This exists for each DMZ object. (FYI: It is not documented, so I wouldn't rely on it's workings for future releases.)

Example:
Code:
$o = new Object();
$o->get_by_id($o->id);
// copy in DataSource 1 properties, but DON'T save it
foreach($datasource2 as $f => $k) {
    if($o->{$f} === $o->stored->{$f}) {
        $o->{$f} = $k;
    }
}
$o->save();

If you need to save it between datasources, then you'll need to work out something else, because there is no way for DMZ to know what is meant by "changed".

Instead of a boolean per field (which may be unwieldy), I recommend creating a TEXT field on the table, and using something like json_encode and json_decode to convert an array of changed fields into a string, and store that on the table. It's a little bigger data-wise, but once you are done with the import, that column can be deleted, removing all of the extra content in one swoop. Alternatively, if this is needed multiple times, simply do a UPDATE <table> SET <column> AS NULL to clear the change history.

[eluser]OverZealous[/eluser]
FYI: I will not be as available as usual this week for answering questions. If I do not respond to your question by next Monday, please re-submit your question, or send me a private message so I can catch the questions I missed.

Thank you everyone for your positive comments. I hope that DMZ continues to be of great assistance to you!

[eluser]mrtavo[/eluser]
[quote author="OverZealous.com" date="1248802573"]@mrtavo
Well, I've never used CI with multiple databases, so I can't help beyond that. I assumed (we all know what that means) that CI wouldn't change the default database when loading auxiliary ones.

What you suggested doing (loading the second database, then reload the first) is how I would have handled it. And then go file a bug report with CodeIgniter, saying that load->database shouldn't replace the default if the second parameter is TRUE. ;-)


@Daniel H
Thanks! I really appreciate it![/quote]


Thanks for your answer and keep working this way Big Grin
DMZ is amazing Wink
Congratulations.

[eluser]Dartmien[/eluser]
[quote author="OverZealous.com" date="1248771673"]You always have to select the 'id' column, due to an old quirk from the original DataMapper. I'd fix it, but I know that it would break a lot of existing code.

So, add select('id'), and you should be all set.[/quote]


Ohh, got it, thanks for the help

[eluser]mcnux[/eluser]
Hi Phil. Good job with 1.4. Loving the querying deep relationships feature. Brilliant!

I am trying to figure out how best to cache a calculated property on my model. For instance, I want to cache the result of someCalculation() on this row so that the next call to someCalculation() returns me the cached result. Obviously if I then move to another row in the instance's recordset I would like the value to be reset.

I am not expecting a complete identity map or anything, simply caching the result for the instance of the model would be fine.

I've had a look through the DataMapper source and so far I think my best bet is DataMapper->fields array?

UPDATE: DataMapper->fields array and setting an instance variable directly, like the other fields? e.g. $this->fields[] = 'myCalculatedProperty' and $this->myCalculatedProperty = 'thecalculatedvalue'?

[eluser]OverZealous[/eluser]
@mcnux
I'm not at all sure what you are trying to do. I don't recommend manipulating the $fields array, since it is expected to be a direct mapping to the database columns.

If you could provide a more concrete example, I may be able to help you. :-)

[eluser]mcnux[/eluser]
[quote author="OverZealous.com" date="1248899005"]@mcnux
I'm not at all sure what you are trying to do. I don't recommend manipulating the $fields array, since it is expected to be a direct mapping to the database columns.

If you could provide a more concrete example, I may be able to help you. :-)[/quote]

Sorry, tried to keep it short as I'm good at going into too much detail! Here's an example:

Code:
// Controller
$car = new Vehicle(3);
$milesDriven = $car->milesDriven();
echo $milesDriven;

$timeOnTheRoad = $car->timeOnTheRoad();
echo $timeOnTheRoad;

$averageSpeed = $car->averageSpeed();
echo $averageSpeed;


// Vehicle Model
function milesDriven(){
  return doLotsOfExpensiveOperationsToGetTheTotal();
}
function timeOnTheRoad(){
  return evenMoreExpensive();
}
function averageSpeed(){
  return $this->milesDriven() / $this->timeOnTheRoad();
}

As you can see, the expensive calculations/db queries/whatever on milesDriven() and timeOnTheRoad() are executed every time they are called. I would like the expensive operation to occur only once, something like:

Code:
// Vehicle Model
function milesDriven(){
  if(!isset($this->miles_driven)){
    $this->miles_driven = doLotsOfExpensiveOperationsToGetTheTotal();
  }
  return $this->miles_driven;
}
function timeOnTheRoad(){
  if(!isset($this->time_on_the_road)){
    $this->time_on_the_road = evenMoreExpensive();
  }
  return $this->time_on_the_road;
}
function averageSpeed(){
  return $this->milesDriven() / $this->timeOnTheRoad();
}

Obviously I could get this to work quite easily but the problem comes when I move to the next row in the recordset and ask for the same property; I somehow need to reset the cached value every time the row is changed.

Yeah I see now that messing around with Model->fields would have been dangerous! Any ideas?

[eluser]jpi[/eluser]
I don't see any problem.

$vehicles->all is an array where each row is a record in your database AND a vehicle object. When a vehicle objet is instantiate the property time_on_the_road and miles_driven should be empty (as they dont refer to a column in your DB). There is no "cached value".

[eluser]OverZealous[/eluser]
[quote author="jpi" date="1248903820"]$vehicles->all is an array where each row is a record in your database AND a vehicle object. When a vehicle objet is instantiate the property time_on_the_road and miles_driven should be empty (as they dont refer to a column in your DB). There is no "cached value".[/quote]

Basically, what he said! You can simply set the field on the objects directly.

If you wanted to make this really seamless, try using the magic __get method:
Code:
// in your Vehicle class
// This method is only called if $field does not exist (PHP feature)
function __get($field) {
    
    if($field == 'milesDriven') {
        $this->milesDriven = // whatever
        return $this->milesDriven;
    } else if($field == 'timeOnTheRoad') {
        $this->timeOnTheRoad = // whatever
        return $this->timeOnTheRoad;
    } //etc.
    
    // Important!  Let DMZ handle everything else
    return parent::__get($field);
}

Then to use, you just do this:
Code:
echo $car->milesDriven;

The great thing about __get is it is only called if the field is not already defined. So, the field will always only be calculated the first time it is called, and the pre-calculated value is returned every time after that.

To force it to be re-calculated, you just call unset($car->milesDriven);




Theme © iAndrew 2016 - Forum software by © MyBB