EllisLab text mark
Advanced Search
1 of 15
1
   
Gas ORM 2
Posted: 18 March 2012 04:49 PM   [ Ignore ]   [ # 11 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

Ok, thanks for the confirmation. I guess i tend to keep the gas repo sync-in with the latest EllisLab repo. But i’ve just adding something to avoid those warning, both in download page and in repo.

Instead re-download, you two can just replace

if ($table != self::$migration['migration_table']

into

if (empty(self::$migration['migration_table']) OR $table != self::$migration['migration_table']

This way, the autogenerator will works both for 2.1 and 2.1++ without throwing some warning.

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 19 March 2012 05:22 AM   [ Ignore ]   [ # 12 ]   [ Rating: 0 ]
Avatar
Joined: 2007-09-05
65 posts

I had the chance to test it yesterday and v2.0 looks really impressive! smile

Great job done as usual.

Stefano

 Signature 

Visit my CodeIgnited webpage @ http://www.stefanogiordano.it

 
Posted: 19 March 2012 10:10 AM   [ Ignore ]   [ # 13 ]   [ Rating: 0 ]
Joined: 2011-05-11
15 posts

Thanks for the fix toopay. The assumption that an _ always indicates a pivot table is not true in this case. I’ll generate the models manually. Ah well, having them automatically generated was a luxury anyway smile.

Now I’m running into this other thing. When I load the Gas ORM Spark, my base_url and site_url are emptied. So

public function index()
{
 $this
->load->helper('url');

 echo 
'base url: ' base_url() . '<br/>';
 
$this->load->spark('gas/2.0.0');
 echo 
'base url: ' base_url() . '<br/>';
returns this to the browser
base urlhttp://local.mysite.com/
base url

Also, I really appreciate how you keep improving the lib. Keep up the good work!

 

 
Posted: 19 March 2012 04:55 PM   [ Ignore ]   [ # 14 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts

I am still working on converting over to Gas ORM 2.0.

I came across a issue that I was hoping to get more information on. In the old version of gas, when Auto Generating models, the fields support ENUM, while the new version does not. Do I need to convert these myself to ENUM of type string.

Old Auto Generated Fields

'id' => Gas::field('auto[16]', array(), ''),

   
'name' => Gas::field('char[64]', array('required'), ''),

   
'description' => Gas::field('string', array(), ''),

   
'recast' => Gas::field('int[3]', array(), ''),

   
'activation_time' => Gas::field('int[2]', array(), ''),

   
'activation_type' => Gas::field('string', array(), 'ENUM'),

   
'skill_points' => Gas::field('int[3]', array(), ''),

   
'slot' => Gas::field('string', array(), 'ENUM'),

   
'chain' => Gas::field('string', array(), 'ENUM'),

   
'created' => Gas::field('datetime', array(), 'TIMESTAMP'),

   
'updated' => Gas::field('datetime', array(), 'TIMESTAMP'), 

New Generated Fields

'id' => ORM::field('auto[16]'),
   
'name' => ORM::field('char[64]'),
   
'description' => ORM::field('string'),
   
'recast' => ORM::field('auto[3]'),
   
'activation_time' => ORM::field('auto[2]'),
   
'activation_type' => ORM::field('string'),
   
'skill_points' => ORM::field('auto[3]'),
   
'slot' => ORM::field('string'),
   
'chain' => ORM::field('string'),
   
'created' => ORM::field('datetime'),
   
'updated' => ORM::field('datetime'), 

I am assuming in the case of Slot, I would convert this too -

'slot' => ORM:: field('string', array(), 'ENUM'), 

The other thing to note, is that for ‘recast’, ‘skill_points’, ‘activation_time’ it has them set to AUTO as opposed to INT, even tough they are in in DB without the Auto Increment flag associated with them.

Additionally, before Gas ORM 2.0 I was using -

private $_types;

 function 
set_types($types{
  $this
->_types = array('types_id' => $types);
  return 
$this;
 
}

function _after_save() {

  
if ($this->empty{

   
// Record ID
   
$id $this->last_id();

   
// _types
   
if(is_array($this->_types)){
    $this
->_types['skills_id'$id;
    
$this->db()->insert('skills_types'$this->_types);
   
}
        

  }

 } 

I am guessing most of this will still work, but maybe I need to convert the insertion to -

if(is_array($this->_types)){
    $nr 
= new Model\Skills\Types();
    
$nr->skills_id $id;
    
$nr->types_id _sets['types_id'];
    
$nr->save();    
   

or

if(is_array($this->_types)){
    $this
->_types['skill_id'$id;
    
Model\Skills\Types::make($this->_types)->save(TRUE);
   

Is there a better way when inserting data with a pivot table?

In this situation I have a one-to-many relationship with skills = types.

So I am updating skills and want to specify the type for it, which goes through the pivot table skills_types, is there a better way?

 
Posted: 19 March 2012 07:29 PM   [ Ignore ]   [ # 15 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts

So last_id() is not working?

I get this error.

An Error Was Encountered

Unknown method
.


  Function  : 
last_id
  File      
: /home/guildwar/public_html/application/models/skills.php
  Line      
82
  Snapshot  

80   // Record ID
81   $id $this->last_id();
82
83   
// _races 
 
Posted: 20 March 2012 12:10 PM   [ Ignore ]   [ # 16 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

@DerLola,

Thanks for the report. I’ve just updated the spark, both for the previous issue(which throw a warning on autogenerate model) and your issue with base_url. Update your spark using this command via CLI :

php tools/spark reinstall gas -
 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 20 March 2012 12:30 PM   [ Ignore ]   [ # 17 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts
Khrome83 - 19 March 2012 04:55 PM

The other thing to note, is that for ‘recast’, ‘skill_points’, ‘activation_time’ it has them set to AUTO as opposed to INT, even tough they are in in DB without the Auto Increment flag associated with them.

What database and dbdriver you use? I’ve just try them, and they generate numeric for INT or TINYINT.

Khrome83 - 19 March 2012 04:55 PM

Is there a better way when inserting data with a pivot table?

You already doing it right, theres no shortcut for create an intermediate record, only cascade delete supported (i’ve never heard about cascade insert anyway). But perhaps, try playing with Gas\Data in your model. I am more convinience to wrap some data into it, instead adding more method just to set-up some property. Gas\Data works this way :

$some_property = new \Gas\Data();

// To set something
// Set some array
$some_property->set('data', array('foo' => 'bar''else' => 'thing'));
// Or...similar with above
$some_property->set('data.foo''bar');
$some_property->set('data.else''thing');

// To get something
var_dump($some_property->get('data')); // will outputing array('foo' => 'bar', 'else' => 'thing')
var_dump($some_property->get('nothing')); // will outputing NULL
var_dump($some_property->get('nothing''default value')); // will outputing 'default value'
var_dump($some_property->get('data.foo')); // will outputing 'bar'
var_dump($some_property->get('data.else')); // will outputing 'thing' 
Khrome83 - 19 March 2012 07:29 PM

So last_id() is not working?

Yes, i change it to insert_id which inherit from CI query builder. Also, just in case you need the whole created resource, you could use :

// Right after create a record...
if ($new_user->save())
{
   
// This will return the last created record in standard Gas instance
   
$last_created Model\User::last_created();
 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 20 March 2012 03:45 PM   [ Ignore ]   [ # 18 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts

@toopay

Thanks for the response. That clears a lot of stuff up for me.

I am assuming you are suggesting to use set function to build a collection, and then follow the standard format for inserting it into the database? This gets rid of the custom methods in the model, as well as the private variables? Is that correct?

Is something that I create in the view or controller, accessible in the model than this way through _after_save()?

So instead of calling a function set_types, I could just set a collection of ‘types’ with the array of data I need. Then when _after_save() is called, insert that information to the correct table?

I am sorry, but I am coming back to PHP and web development after my career with Game Design didn’t go anywhere after a few years. OOP PHP 5 is new to me entirely, as well as frameworks like CI, so it’s been a little slow for me grasping things.

Ruby on Rails actually has a cascade insert. I only played with ROR for a few weeks using the CodeSchool Zombies for Rails and some side project, but I could so something like this (provided in my limited knowledge I understood what was going on).

This is my best PHP interpretation for mythical GAS ORM with cascade insert -

$data = array(
'name' => 'Bob',
'email' => 'bob@email.com',
'job' => find_by_name('M$'),
'pay' => array('amount' => '2000''frequency' => '2 weeks'),
);

Model\User::make($data); 

I imagine additional arrays would be new record for table Pay, and would insert into User_Pay the correct IDs, while find_by_name would look in table Job for the existing record and make the correct IDs in User_Job.

This could be super far off plausible, like I said I am just getting back into this so my knowledge is super limited.

This is everything I have on my Database setup. I just switched to a new host that uses CPanel so still learning where all the info is listed. I hope this answers your question about my database.

ServerLocalhost via UNIX socket
Server version
5.1.56-log
Protocol version
10
User
guildwar@localhost
MySQL charset
UTF-8 Unicode (utf8)
Web server

cpsrvd 11.30.4.6
MySQL client version
5.1.56
PHP extension
mysql 
 
Posted: 20 March 2012 04:41 PM   [ Ignore ]   [ # 19 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts
Khrome83 - 20 March 2012 03:45 PM

I am assuming you are suggesting to use set function to build a collection, and then follow the standard format for inserting it into the database? This gets rid of the custom methods in the model, as well as the private variables? Is that correct?

Is something that I create in the view or controller, accessible in the model than this way through _after_save()?

So instead of calling a function set_types, I could just set a collection of ‘types’ with the array of data I need. Then when _after_save() is called, insert that information to the correct table?

Correct, and yes that property should be accesible.

Regarding your database, it all seems ok. But again, i could not replicate those behaviour. From here, everything generated in appropriate datatype. I will check that a little while, and wait to see if someone else have same issue.

Khrome83 - 20 March 2012 03:45 PM

This is my best PHP interpretation for mythical GAS ORM with cascade insert -

$data = array(
'name' => 'Bob',
'email' => 'bob@email.com',
'job' => find_by_name('M$'),
'pay' => array('amount' => '2000''frequency' => '2 weeks'),
);

Model\User::make($data); 

I imagine additional arrays would be new record for table Pay, and would insert into User_Pay the correct IDs, while find_by_name would look in table Job for the existing record and make the correct IDs in User_Job.

In case you still dont realize, the new relationship method within this version. You could have, for example, something like this in your relationship configuration :

'role' => ORM::has_many('\\Model\\Acl\\User => \\Model\\Acl <= \\Model\\Acl\\Role => \\Model\\Role'), 

So new relationship method could be more than 2 level deep, not like the old one. So, this thing adding some complexity, to apply something like ‘cascade_insert’.

In the past, someone is already asking the same. And for me, the callback which available for that point (after_save) most likely resolving the need to create and linked the last created record to some many-to-many relationship with other entity. And so far, i dont have any difficulty to set up that way.

But i will consider this idea, and i may include this behaviour in next minor release. Maybe something like this :

// Perhaps, this only works for 2 level deep relationship
$new_user Model\User::with_job($jobdata)->create($userdata)->save();
// So it slightly "uniformal" with cascade delete :
// Model\User::with('job')->delete(1); 
 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 20 March 2012 07:05 PM   [ Ignore ]   [ # 20 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts

Thanks toopay for all the feedback and information. I really appreciate it.

 
Posted: 21 March 2012 10:32 AM   [ Ignore ]   [ # 21 ]   [ Rating: 0 ]
Joined: 2008-12-11
18 posts

I have to say that i really hate escaping table references \\table within has_many declaration or in other strings :(

 
Posted: 21 March 2012 11:06 AM   [ Ignore ]   [ # 22 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts

Setting up your model relationship is one-time set-up, unless in the future, you need to change your table schema smile

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
Posted: 21 March 2012 12:11 PM   [ Ignore ]   [ # 23 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts

@toopay - I could not get the properties to be accessible in the model when set in the view. So I was not able to use Gas\Data(). I did however spend a few hours playing around and figured this out. I think this is a more elegant way to set up the pivot tables, as it’s universal for all my pivot tables and did not require a custom method per pivot table, or a separate entry for each addition.

I still need to do some testing, and I need to add validation to make sure _pivot contains data.

So when creating a record, call function on the model set_pivot. This takes all the table names (lowercase) and the ID if the associated record. Also pass the name of the model, this was just to make the code easier to copy and paste from model to model.

$contents = array(
     
'name' => 'Heal as One',
     
'description' => 'Heal yourself and your pet',
     
'recast' => '20'
    
);

   
$newrecord Model\Skills::make($contents);
   
$newrecord->set_pivot(array(
     
'types' => '3',
     
'pets' => '1',
     
'weapons' => '1',
     
'professions' => '3'
    
), 'skills');


   if(
$newrecord->save()) {
    
echo 'New Record Saved';
   
else {
    
echo 'Foo not saved. Error were '.$foo->errors('<p class="error">''</p>');
   

Then in the model add these private fields -

private $_pivot;
    private 
$_model

The set_pivot function -

function set_pivot($collection$model{
  $this
->_pivot $collection;
  
$this->_model $model;
  return 
$this;
 

Then add this into _after_save() -

if ($this->empty{
   
// Record Id
   
$id $this->insert_id();

   
// Insert Into Appropriate Pivot Tables
   
foreach ($this->_pivot as $key => $value{
    $contents[$key
.'_id'$value;
    
$contents[$this->_model.'_id'$id;
    
$class 'Model\\'.ucfirst($this->_model).'\\'.ucfirst($key);
    
$class::make($contents)->save(TRUE);
    unset(
$contents);
   


  } 

Calling make dynamically could not be done without eval before, but thanks to PHP 5.3 this is now valid.

So now it will insert a new entry for any relations that are provided. Obviously this works for me because I follow the default conventions for naming the pivot table foreign keys. I am sure there is a better way to make this worth with the scheme overrides included in the models.

 
Posted: 21 March 2012 03:07 PM   [ Ignore ]   [ # 24 ]   [ Rating: 0 ]
Joined: 2012-03-09
23 posts

A few questions on finder?

What is the difference between

$skills Model\Skills::all(); 

and

$skills Model\Skills::with('types','professions')->all(); 

When I use either, i still get access to the information regardless if I include With().

I am printing everything as such -

foreach ($skills as $s{
    
echo $s->name.'<br />';
    foreach (
$s->types() as $t){
     
echo $t->name.'<br />';
    
}
    
foreach ($s->professions() as $p{
     
echo $p->name.'<br />';
    
}
    
foreach ($s->weapons() as $w{
     
echo $w->name.'<br />';
    
}    
   } 

So even if weapons are not included, I can still access them? So what does with get me?

Also when I do -

$skills Model\Skills::find(1); 

I can no access any of the relationships (types, professions, weapons, etc).

 
Posted: 21 March 2012 03:31 PM   [ Ignore ]   [ # 25 ]   [ Rating: 0 ]
Avatar
Joined: 2010-12-20
1586 posts
Khrome83 - 21 March 2012 03:07 PM

A few questions on finder?

What is the difference between

$skills Model\Skills::all(); 

and

$skills Model\Skills::with('types','professions')->all(); 

When I use either, i still get access to the information regardless if I include With().

Yes, you will still get access to the related entity without eager load (with method). The different is on the executed queries. With the first one, you actually will generate SELECT statement as many as your records, but with eager load it minimize the query. To find out, try adding this line :

$this->output->enable_profiler(TRUE); 

And try to access the related entity with eager load, and try without it. You will see the different.

Khrome83 - 21 March 2012 03:07 PM

Also when I do -

$skills Model\Skills::find(1); 

I can no access any of the relationships (types, professions, weapons, etc).

What you mean “no access” here?

 Signature 

“In Code We Trust.”


CI Library : Gas ORM | Proxy

 
1 of 15
1