Closed ghost closed 10 years ago
I don't see any manipulation ocurring here. Please can you provide actual code so I can see your intentions more clearly.
I don't see why you can't use find_array here with the current samples you've provided. array_filter or array_map combined with find_array should cover all the situations a result_set or an array from find_many could anyway.
I agree with you @treffynnon. And I used find_array() function in my code till I start using idiorm/paris. Let's see some code:
class User extends Model {
public function tweets() {
return $this->has_many('Tweet');
}
}
class Tweet extends Model {}
$users = Model::factory('User')->find_many();
foreach ($users as $user) {
$user->tweets = $user->tweets()->find_many();
}
And you can clearly see that if I use find_array() function then I can't use tweets() method.
Model::factory('User')->find_array();
foreach ($users as $user) {
$user['tweets'] = $user->tweets()->find_array(); // Invalid - use tweets() method of non-object
}
Yep, so that is why I was asking. Unfortunately Idiorm is constrained by the same universal laws as the rest of the world. Convenience comes with a cost - if you want to use the quick methods like that then you're going to have to pay the performance price.
When you query like that in a loop you're actually generating a query for each iteration of the loop so it must hit the database each time. Queue slow down.
This is where the 80/20 rule from Idiorm's philosophy really kicks in - joins, which look like a fit for speeding up these queries quickly are not automatically generated so you'll have to build them yourself with the query builder.
I would recommend a static method on your model that you specify this query in yourself.
Yeap, I understand you. But it's true when use "one-to-one" relationship, then it's better way to use "join" feature, I agree with you. And what if I need to get result in case of "one-to-many" relationship? Anyway I make a query in a loop to reach the goal, and it would be better if I'll be able to use model objects and then convert them to json format. I'm interested in your opinion.
Try this:
class User extends Model {
public function tweets() {
return $this->has_many('Tweet');
}
}
class Tweet extends Model {}
$jsonUsers = array();
foreach (Model::factory('User')->find_result_set() as $user) {
$u = $user->as_array();
$u['tweets'] = $user->tweets()->find_array();
$jsonUsers[] = $u;
}
The problem is you have to sacrifice performance somewhere, so you have to choose whether you want to sacrifice DB performance by having lots of queries or do you want to sacrifice PHP performance by having sifting loops?
@redjee, So far as converting to Json, that's easily accomplished, as I'm sure you're aware. In the hopes that perhaps it might help you or others, I've included a reduced form of how I deal with JSON using Paris, below. I've done a little extra work, as I sometimes want a JSON object with all of the relationships included, and sometimes I don't.
trait JsonModel
{
/**
* @param $full bool Whether relationships should be fetched and added to the eventual JSON object;
*/
public function toJson($full = false)
{
return json_encode($this->jsonSerialize(), DEBUG ? JSON_PRETTY_PRINT : null);
}
/**
* This method fulfills the signature for JsonSerializeable interface.
* @param $full bool Whether relationships should be fetched and added;
*/
public function jsonSerialize($full = false)
{
// ...
// I choose to always add 'model' and 'canonical' (url) to json data.
// I've removed that code, but simply add those as lines in array_merge parameter
return array_merge(
$this->asArray(),
$full ? $this->jsonSerializeMore() : []
);
}
/**
* Override when necessary, if you want to pass relations in the same object.
*/
protected function jsonSerializeMore() {
return [];
}
} // end trait
class Foo extends \Model implements \JsonSerializable
{
use \Phibula\Models\Traits\JsonModel; // Adjust namespace, of course
}
I know that I can use find_array function, but I need to manipulate objects in array before convert to json format.
I found another way to reach the goal:
But it's bad in performance. I need find_many function, but it must return not empty data array when convert to json.