Best way to get readable data from id - php

i was getting in a question when i got this scenario:
I have to make a history log about what the user does and of course the user can do a lots different action.
i thought two different 2 way for make it i just need someone that can help me to follow the right way.
First way:
Create 2 different tables
History_user
History_type
History_user table
id | user_id | history_type (int)
1 1 1
1 3 2
History_type
id | name_action (string)
1 The user has posted on the wall
2 The user has change his profile picture
and then just join on the query with History_user.history_type = History_type.id
Second way:
is create the History_user table and an helper example called Converter.
<?php
class Converter {
function history($type_history) {
switch($type_history) {
case 1:
$human_history = "The user has posted on the wall";
break;
case 2:
$human_history = "The user has change his profile picture";
break;
}
return $human_history;
}
}
$converter = new Converter();
$converter->history(1);
I was looking for the better way for do that, in terms of performance and maintainability. Thank you.

Both helper and History_type table are necessary for information representation. In terms of performance it doesn't really matter, because you will insert only in one table on user action. If you need to represent data, you will need just one more query to get descriptions of actions (without joins, ofc, if you want some performance). So 2 tables way is more flexible and extendable.
You still could do that helper function which lets say will have static cache variable - array of id => name of actions, which will be lazy loaded on history() function like this:
class Converter {
protected static $_cache;
protected static function _loadCache() {
if (null !== self::$_cache) {
return;
}
self::$_cache = array();
$query = "SELECT * FROM `History_type`";
$res = mysql_query($query);
while ($row = mysql_fetch_assoc($res)) {
self::$_cache[(int) $row['id']] = $row['action'];
}
}
public static function history($id) {
self::_loadCache();
return isset(self::$_cache[$id]) ? self::$_cache[$id] : 'Undefined action';
}
}
Converter::history(1);

Related

Fetch data from many to many relationship with eloquent

I have 2 models, store and dvd with many to many relationship
dvd model:
public function stores() {
return $this->belongsToMany('App\store');
}
store model:
public function dvds ( ) {
return $this->belongsToMany('App\dvd');
}
Then, in controller, when I need fetch data from both models, I use code like this:
$res_store = store::orderBy("id","desc")->get();
foreach( $res_store as $row ) {
$dvds = $row->dvds()->get();
foreach ($dvds as $dvd) {
// echo columns here
}
}
This works, but my question is, I'm doing this in correct way? I'm asking because it seems 2 loops for this simple relation is somehow inefficient.
No, this is not the right way.
When looping over a $store, you can access the associated $dvd records via $store->dvds; there is no need to call $row->dvds()->get(), as that is executing a new query with the same result of $store->dvds. Full code should simply be:
$stores = Store::with("dvds")->orderBy("id", "DESC")->get();
foreach($stores AS $store){
foreach($store->dvds AS $dvd){
... // Do something with `$dvd`
}
}
The ::with("dvds") clause is known as "Eager loading", and prevents $store->dvds from needing execute another query behind the scenes.
Also, please name your models correctly. Classes in PHP are StudlyCase, so Store and DVD, not store and dvd.

2-table interaction: insert, get result, insert

I need to make a fundamental decision of my database/web interaction and I am missing the knowledge to even find proper search terms.
Background:
I am building a family website which supports a forum, family tree, pvp games with rankings and more details, all from a datamodel. Technologies right now: Php, MySQL, javascript in object oriented fashion.
Requirement:
In a forum datamodel, process a written post as addition of a new forum topic (thread).
Current approach:
In my current datamodel this would imply and update on two tables: Post and Topic.
I would need to insert a row in the topic table, then get the newly generated topicId(sequence), and then use that in an insert to the post table.
Problem:
I feel this is too much work for what needs to happen, too much interaction.
But it will become a typical requirement if I stick with the current approach.
Question:
am I on the right track anyway or should I
restructure the datamodel or
pick another way of database interaction (e.g. stored procedures)
am I facing a typical example where you would use methodology/framework xyz.
Currently tables have following structure (loosely based on this one from erdiagrams.com)
TOPIC: ('thread')
id
Forum_ID (FK)
Person_ID (FK)(threadcreator)
IsLocked
IsSticky
Subject
ViewCount
DateCreated
Tc_post_id - trigger to last post_id in this thread
POST
id
topic_id(FK)
person_id(FK)
subject
message
timestamp
replyto
Then I have a view that collects the last post for each topic and displays some info on that as well (e.g. last poster image) over the trigger Tc_post_id.
Ad 1 and 2: Your data model is fine. Using foreign keys is crucial here. One more thing that you need to take care of is that the database should ensure there is a TOPIC record for each POST. This is done by setting POST.topic_id NOT NULL attribute. This is sufficient safety mechanism on the DB side, as it ensures that no POST will be left without TOPIC. No matter what you do now with your POST you are obligated to provide a TOPIC.
Ad 3: A trigger with stored procedure is not recommended here as you have additional data in your TOPIC table (IsSticky, IsLocked, etc), which you might want to provide upon TOPIC record creation. Also, if such a trigger would be applicable, the database design would be a subject to denormalization.
Ad 4: On the business logic side you can now aid yourself by writing a automated mechanism to create the TOPIC record every time a new POST record is created without specified topic_id. I recommend using some ORM for this or take advantage of the data models available in any MVC framework. The blueprint for such models would look like this:
abstract class AModel // this class should be provided by ORM or framework
{
/**
* #var PDO
*/
protected $_db_driver;
public function getLastInsertId()
{
$stmt = $this->_db_driver->prepare('SELECT LAST_INSERT_ID() AS id');
$stmt->execute();
return $stmt->fetch(PDO::FETCH_OBJ)->id;
}
public abstract function getFieldList();
}
class ForumTopicModel extends AModel
{
public function insert(array $data)
{
$sql = 'INSERT INTO topic VALUES (:id, :forum_id, :person_id, :is_locked, ...)';
$stmt = $this->_db_driver->prepare($sql);
return $stmt->execute($data);
}
public function getFieldList()
{
return array('id', 'forum_id', 'person_id', 'is_locked', /*...*/);
}
// ...
}
class ForumPostModel extends AModel
{
public function insert(array $data)
{
$sql = 'INSERT INTO post VALUES (:id, :topic_id, :person_id, :subject, ...)';
$stmt = $this->_db_driver->prepare($sql);
return $stmt->execute($data);
}
public function getFieldList()
{
return array('id', 'topic_id', 'person_id', 'subject', /*...*/);
}
public function insertInitialTopicPost(array $form_data)
{
$this->_db_driver->beginTransaction();
$result = true;
if ( empty($form_data['topic_id']) ) {
// no topic_id provided, so create new one:
$topic = new ForumTopicModel();
$topic_data = array_intersect_key(
$form_data, array_flip($topic->getFieldList())
);
$result = $topic->insert($topic_data);
$form_data['topic_id'] = $topic->getLastInsertId();
}
if ( $result ) {
$forum_post_data = array_intersect_key(
$form_data, array_flip($this->getFieldList())
);
$result = $this->insert($forum_post_data);
}
if ( $result ) {
$this->_db_driver->commit();
}
else {
$this->_db_driver->rollBack();
}
return $result;
}
// ...
}
Note: as a good MVC practice those models should be the only place to directly operate on the table rows. Otherwise you'll end up getting SQL errors (but the data model will remain coherent, so you don't have to worry that something will break).
Finally take advantage of your models in the controller layer:
class ForumPostController extends AController
{
public function createInitialTopicPostAction()
{
$form_data = $this->getRequest()->getPost(); /* wrapper for getting
the $_POST array */
// (...) validate and filter $form_data here
$forumPost = new ForumPostModel();
$result = $forumPost->insertInitialTopicPost($form_data);
if ( $result ) {
// display success message
}
else {
// display failure message
}
}
}
The way I understand it: topics are containers of posts.
Topics table would be rather minimal, and would perhaps only contain a topic id (PK) and topic title.
The posts themselves will contain post id (PK), topic id (FK), timestamps, author id, text.
I would utilize InnoDB and foreign keys, so a topic that is deleted could delete all of its child posts.
(edit:)
In this answer I posted a way to do it using mysql_insert_id(), which would be still a technically correct solution (correct me if wrong).
However instead I will now go for the PDO wrapper I guess. And also, this is not an answer to the general modeling/approach question.
Still, following would be a way to do it:
$sql = "INSERT INTO topic VALUES (NULL,'$forumId',<more parameters>)";
$result = mysql_query($sql);
# get the generated id
$topicId = mysql_insert_id();
# and insert into the post table
$sql = "INSERT INTO post VALUES (NULL,'$topicId',<more parameters>)";
$result = mysql_query($sql);
mysql_free_result($result);
Source: http://www.desilva.biz/mysql/insertid.html

Custom is_unique_logical_key - validation or callback?

Can I please have a design suggestion for the following problem:
I am using Codeigniter/Grocery_CRUD.
My system is multi tenanted - different autonomous sites - within the same client. I have quite a few instances of tables that have unique logical keys. One such table structure is:
equip_items
id (pk)
equip_type_id (fk to equip_types)
site_id (fk to sites)
name
Where (equip_type_id, site_id, name) together are a unique key in my db.
The issues is that when using a grocery_CRUD form to add or edit a record that breaks this database rule - the add or edit fails (due to the constraints in the db) but I get no feedback.
I need a variation on the is_unique form_validation rule by which I can specify the field*s* that must be unique.
The issues:
How to specify the rule? set_rules() is for a given field and I have multiple fields that the rule will apply to. Does that mean I should abandon the Form_validation pattern? Or do I follow the 'matches' rule pattern and somehow point to the other fields?
Perhaps a callback function would be better but this would mean writing a custom function in each model where I have this problem at last count this is 9 tables. It seems far better to do this in one place (extending form_validation).
Am I missing something already in codeigniter or grocery_CRUD that has already solved this problem?
Any suggestion/advice you might have would be appreciated.
EDIT:
Actually it appears the solution Johnny provided does not quite hit the mark - it enforces each field in unique_fields() being independently unique - the same as setting is_unique() on each one. My problem is that in my scenario those fields are a composite unique key (but not the primary key). I don't know if it is significant but further to the original problem statement: 1) site_id is a 'hidden' field_type - I don't want my users concerned they are on a different site so I'm dealing with site_id behind the scenes. 2) Same deal with an equip_status_id attribute (not part of the unique key). And 3) I have set_relations() on all these foreign key attributes and grocery_CRUD kindly deals with nice drop downs for me.
EDIT 2
I have solved this using a callback.
UPDATE: This code is now part of grocery CRUD version >= 1.4 and you don't need to use an extension anymore. For more see the documentation for unique_fields
I will try to explain it as easy as I can:
1. First of all for those who have grocery CRUD lower or equal to 1.3.3 has to use this small change: https://github.com/scoumbourdis/grocery-crud/commit/96ddc991a6ae500ba62303a321be42d75fb82cb2
2. Second create a file named grocery_crud_extended.php at application/libraries
3. Copy the below code at your file application/libraries/grocery_crud_extended.php
<?php
class grocery_CRUD_extended extends grocery_CRUD
{
protected $_unique_fields = array();
public function unique_fields()
{
$args = func_get_args();
if(isset($args[0]) && is_array($args[0]))
{
$args = $args[0];
}
$this->_unique_fields = $args;
return $this;
}
protected function db_insert_validation()
{
$validation_result = (object)array('success'=>false);
$field_types = $this->get_field_types();
$unique_fields = $this->_unique_fields;
$add_fields = $this->get_add_fields();
if(!empty($unique_fields))
{
$form_validation = $this->form_validation();
foreach($add_fields as $add_field)
{
$field_name = $add_field->field_name;
if(in_array( $field_name, $unique_fields) )
{
$form_validation->set_rules( $field_name,
$field_types[$field_name]->display_as,
'is_unique['.$this->basic_db_table.'.'.$field_name.']');
}
}
if(!$form_validation->run())
{
$validation_result->error_message = $form_validation->error_string();
$validation_result->error_fields = $form_validation->_error_array;
return $validation_result;
}
}
return parent::db_insert_validation();
}
protected function db_update_validation()
{
$validation_result = (object)array('success'=>false);
$field_types = $this->get_field_types();
$unique_fields = $this->_unique_fields;
$add_fields = $this->get_add_fields();
if(!empty($unique_fields))
{
$form_validation = $this->form_validation();
$form_validation_check = false;
foreach($add_fields as $add_field)
{
$field_name = $add_field->field_name;
if(in_array( $field_name, $unique_fields) )
{
$state_info = $this->getStateInfo();
$primary_key = $this->get_primary_key();
$field_name_value = $_POST[$field_name];
$ci = &get_instance();
$previous_field_name_value =
$ci->db->where($primary_key,$state_info->primary_key)
->get($this->basic_db_table)->row()->$field_name;
if(!empty($previous_field_name_value) && $previous_field_name_value != $field_name_value) {
$form_validation->set_rules( $field_name,
$field_types[$field_name]->display_as,
'is_unique['.$this->basic_db_table.'.'.$field_name.']');
$form_validation_check = true;
}
}
}
if($form_validation_check && !$form_validation->run())
{
$validation_result->error_message = $form_validation->error_string();
$validation_result->error_fields = $form_validation->_error_array;
return $validation_result;
}
}
return parent::db_update_validation();
}
}
4. Now you will simply have to load the grocery_CRUD_extended like that:
$this->load->library('grocery_CRUD');
$this->load->library('grocery_CRUD_extended');
and then use the:
$crud = new grocery_CRUD_extended();
instead of:
$crud = new grocery_CRUD();
5. Now you can simply have the unique_fields that it works like this:
$crud->unique_fields('field_name1','field_name2','field_name3');
In your case:
$crud->unique_fields('equip_type_id','site_id');
Pretty easy right?
This is checking if the field is unique or not without actually change the core of grocery CRUD. You can simply use the grocery_CRUD_extended instead of grocery_CRUD and update grocery CRUD library as normal. As I am the author of the library I will try to include this to grocery CRUD version 1.4, so you will not have to use the grocery_CRUD_extended in the future.
I have done this using a callback:
$crud->set_rules('name','Name','callback_unique_equip_item_check['.$this->uri->segment(4).']');
function unique_equip_item_check($str, $edited_id)
{
$var = $this->Equip_Item_model->is_unique_except(
$edited_id,
$this->input->post('site_id'),
$this->input->post('equip_type_id'),
$this->input->post('name'));
if ($var == FALSE) {
$s = 'You already have an equipment item of this type with this name.';
$this->form_validation->set_message('unique_equip_item_check', $s);
return FALSE;
}
return TRUE;
}

CodeIgniter2 -- Working with 2 table relationships

new to CodeIgniter and MVC/OOP as well. My current problem that I am trying to work through involves 2 tables.
Gallery Table
id
name
clientID
Client Table
id
Name
The gallery['clientID'] references the client['id'] so I can retrieve the name. Currently my gallery_model.php file looks like
class Gallery_model extends CI_Model
{
public function __construct()
{
$this->load->database();
}
//Get all in progress galleries from client
public function get_progress($id = FALSE , $clientRef = '205')
{
if($id == FALSE) {
$query = $this->db->get_where('gallery', array('clientRef' => $clientRef, 'finish' => '0' ));
return $query->result_array();
}
}
//Get all proofed galleries from client
public function get_proofed($id = FALSE , $clientRef = '205')
{
//get all galleries from client
if ($id == FALSE) {
$query = $this->db->get_where('gallery',array('clientRef' => $clientRef, 'finish' => '1'));
return $query->result_array();
}
}
//get the gallery selected
public function get_gallery($id , $clientRef = '205')
{
//This returns individual galleries
$query = $this->db->get_where('gallery', array('id' => $id));
return $query->row_array();
}
}
My controller looks like:
public function index()
{
//Proofed Albums
$data['gallery'] = $this->gallery_model->get_proofed();
//Albums that are in progress
$data['in_progress'] = $this->gallery_model->get_progress();
$this->load->view('templates/header',$data);
$this->load->view('gallery/index',$data);
$this->load->view('templates/footer');
}
Then the view's out put is
$gallery['name'] - $gallery['clientId']
What is the best practice for something like this. I know it's probably simple, but I want to start out doing this correctly. Should I use $this->db->join();
Thanks in advance for the help on this.
Following up on William's answer, you can do a join using CI's Active Record
$this->db->from('gallery')->join('client', 'gallery.id = client.id')->get()
Using $this->db->join() is indeed the best (and the only way done via Active Records without adding your own SQL) way to get information from several tables all in one query.
You're probably already aware of this, but just in case (and for the benefit of future people visiting this page), the CodeIgniter User Guide has a nice page detailing how to use Active Records.
The default of Inner Join should be fine for your purposes. If you have gallery entries without clients linked to them and you want them to be included in the results, then you may want to consider the other types of join, which you can read about here.

Creating nested relationships with an ORM and minimizing queries

Edit 3
After reading a boat load I really don't think with any ORM or system in general it is possible to build the relationships of organized objects like I want in fewer queries that I am using. If any can provide an example of it being possible I would kiss you.
In Edit 2 The nested for loops I think is the best solution running
Total_queries = 1 + 2(Slides_in_project) + Shapes_in_project
| | \
Query to get project | \
| \
Query to get slides and double because of points \
\
Get all the shapes in the project
I would love a better example because to populate simple projects I would probably be running 200-500 queries. This is bad.
Edit 2
Well I have been playing with this for a while now and I have some results but I do not think they are the "RIGHT" way and that matters to me a lot. What I do is I use the where_related method to get the right objects but I think my query count is still pretty high and I know an ORM can do better. When I use the where related to create the proper hierarchy I have to use nested foreach loops and I don't like that. That means useless querying.
Here is the solution I came up with
function get_project_points($link_id)
{
echo "<pre>";
foreach($this->where('link_id', $link_id)->get()->slide->where_related('project', 'id', $this)->get() as $slide){
echo $slide->id."<br>";
foreach($slide->shape->where_related('slide', 'id', $slide->id)->get() as $shape){
echo "\t".$shape->id."<br>";
foreach ($shape->point->where_related('shape', 'id', $shape->id)->get() as $point) {
echo "\t\t".$point->id."<br>";
}
}
}
}
This outputs a nice tiered structure and as you can see it would be easy to replace the echos with object/array population.
What I would rather have though is one chained command that did the same thing if possible that way scoping isn't an issue either.
Some chain more resembling
$this->where('link_id', $link_id)->get()
->slide->where_related('project', 'id', $this)->get()
->shape->where_related('slide', 'id', $slide->id)->get()
->point->where_related('shape', 'id', $shape->id)->get()
That of course does not achieve anywhere near the same results as the nested foreach loops but what I would like to know is it possible to chain relationships and populate objects without nested foreach
So I just did some profiling and the nested foreach loops generate 63 queries on a small project, and take almost half a second to generate results. This is really too slow. There must be a better query.
__________Edit 1
All the below information is great but I have been playing with it and I cannot seem to get any relationship to work let alone a 3 tiered one. I have tried just about everything I can think of and read the doc's but for somereason my brain doesn't like the ORM.
I would like to just echo the id's of all slides in a project. I will give a list of what I have tried with no avail. My model structure is the same as below I am just adding methodes.
class Project extends DataMapper {
var $has_many = array("slide");
function get_project_slides($link_id)
{
$this->where('link_id', $link_id)
->where_related('slides', 'project_id'
$this->where('link_id', $link_id)->get()->id
)
->get();
}
}
And I have tried what I would think is the logical opposite in the Slide Method.
What am I doing wrong... How do you structure ORM relationships?
Original Question
I am using an ORM for the first time and I am having huge problems visualizing how to structure the code to pull data from the relationships.
I am using DataMapper as my ORM with CodeIgniter. I have the installation working just fine and I read all the docs, I just cannot get my head around how to get information in controllers
+-----------+ +------------+ +---------+ +----------+
| projects | | slides | | shapes | | points |
+-----------+ +------------+ +---------+ +----------+
| id | | id | | id | | id |
+-----------+ | project_id | |slide_id | | shape_id |
+------------+ +---------+ | x |
| y |
+----------+
Models -
project.php
class Project extends DataMapper {
var $has_many = array("slide");
}
// End of project.php
// Location: ./application/models/project.php
slide.php
<?php
class Slide extends DataMapper {
var $has_many = array("shape");
var $has_one = array("project");
}
// End of slide.php
// Location: ./application/models/slide.php
shape.php
<?php
class Shape extends DataMapper {
var $has_many = array("point");
var $has_one = array("slide");
}
// End of shape.php
// Location: ./application/models/shape.php
point.php
<?php
class Point extends DataMapper {
var $has_one = array("shape");
}
// End of point.php
// Location: ./application/models/point.php
The above should create a decending one->many relationship between projects->slides->shapes->points
How do you start to deal with information? When I was not using an ORM I handled all data processing in the Model is this incorrect for the ORM Models? Say you wanted to get all the points in all the shapes in project 1 how would you go about structuring such a call?
I don't really need specific code if you want that would be helpful. What I really need is some ideas on how to visualize how to tier the objects so you can deal with each at any tier.
First of all, I'm sorry to break this to you , but CodeIgniter's DataMapper is actually a variation of ActiveRecord pattern.
If you care, you compare the real DataMapper pattern with its counterpart - ActiveRecord. In short - difference is in fact that in DM pattern you Domain Object is unaware of type ( and even the existence ) of storage. It is used in manner like $mapper->store( $user );.
"Favor object composition over class
inheritance." © GoF
That said..
If i read the examples right then it should work like this:
( i am assuming that relationships between 'entities' are already established )
class Project extends DataMapper
{
// --- the rest of your stuff
public function get_all_points()
{
$points = array();
$slides = $this->slide->get()->all;
foreach ( $slides as $slide )
{
$shapes = $slide->shape->get()->all;
foreach ( $shapes as $shape )
{
$points = array_merge( $point = $shape->point->get();
}
}
return $points;
}
}
Then you can use something like
$project = new Project;
$all_points = $project->where( 'id' , 1 )->get_all_points();
foreach ( $all_points as $point )
{
$point->x = 0;
$point->save();
}
This should gather all th points that are related to project with ID 1, and set the X value to 0 and store each in the database .. not that any sane person would do it.
I am not using any sort of ORM, that's why i really hope i got this wrong, because this looks to me like an abomination.
I'm not sure how Datamapper does it but I have a custom GenericObject model for Codeigniter that does ORM like this:
class Article extends GenericObject
{
public $relationships = array ( "has_many" => array ("comments"), "has_one" => array ("users") );
}
class Comments extends GenericObject
{
public $relationships = array ( "belongs_to" => array ("articles", "users"), "has_one" => array ("users") );
}
class Users extends GenericObject
{
public $relationships = array ( "has_many" => array ("comments", "articles") );
}
If I want to get everything from a User then I can just do something like:
$User = new User( $some_user_id );
$User->boot_relations("all");
foreach ($User->Comments as $Comment)
{
echo $Comment->title."<br />";
echo $Comment->body."<br />";
echo "written by ".$User->username;
}
So it can be fairly elegant (or at least I like to think so).
With most relational data, I typically lazy-load objects at they are needed. I'm not a PHP developer, but here's what I would do in pseudo-code.
class Projects {
var slides = null;
function getSlides() {
if(slides == null) {
slides = getSlidesForProject(this.id);
}
return slides;
}
}
class Slides {
var shapes = null;
function getShapes() {
if(shapes == null) {
shapes = getShapesForSlide(this.id);
}
return slides;
}
}
class Shapes {
//... same as Projects.getSlides and Slides.getShapes
}
Unfortunately, this causes multiple calls to the database if you needed to get all Points for a Project.
With any MVC solution, I recommend going with a light Controller and a heavy Model to make code reuse and testing easier.
First off : I don't know anything about CI's own ORM implementation, but when I see what you are doing, either it's missing some functionality or you're using it in the wrong way (from your edit #2).
In Propel however (just mentioning this because that's what I use most if the time, Doctrine is another good alternative) these things are easily done, especially in the new 1.6 branch, using fluent interfaces. Just check out the docs on Relationships. Doesn't that look like something you'd want to use? :p
From what I understand, you want to retrieve one project with all the associated points, given the constraints between each table.
Check this sqlFiddle: http://sqlfiddle.com/#!2/9ed46/2
Schema cration:
CREATE TABLE project
(
id int auto_increment primary key,
name varchar(20)
);
CREATE TABLE slide
(
id int auto_increment primary key,
name varchar(20),
project_id int
);
CREATE TABLE shape
(
id int auto_increment primary key,
name varchar(20),
slide_id int
);
CREATE TABLE point
(
id int auto_increment primary key,
name varchar(20),
shape_id int
);
Request:
select project.id as project_id, project.name as project_name,
slide.id as slide_id, slide.name as slide_name,
shape.id as shape_id, shape.name as shape_name,
point.id as point_id, point.name as point_name
from project
left join slide on slide.project_id = project.id
left join shape on shape.slide_id = slide.id
left join point on point.shape_id = shape.id
where project.id = 1
It returns something like this:
PROJECT_ID PROJECT_NAME SLIDE_ID SLIDE_NAME SHAPE_ID SHAPE_NAME POINT_ID POINT_NAME
1 fst_project 1 fst_slide 1 fst_shape 1 first_pt
1 fst_project 1 fst_slide 1 fst_shape 2 2nd_pt
...
By processing this output, you could construct an object tree that is like you want, everything in 1 query. But this post-processing may take some time. You would have to loop through each point.
Have a look at Granada.
From the readme:
class User extends Model {
public static $_table = 'user';
public function post(){
return $this->has_many('Post');
}
public function avatar(){
return $this->has_one('Avatar');
}
}
You can include relationships inside your relationships !
$user_list = Model::factory('User')->with(array('post'=>array('with'=>'comments')),'avatar')->find_many();
It will make 3 querys:
SELECT * FROM user
SELECT * FROM avatar WHERE user.id IN (......)
SELECT * FROM post WHERE user.id IN (.....)

Categories