SitePoint Sponsor

User Tag List

Page 5 of 7 FirstFirst 1234567 LastLast
Results 101 to 125 of 171
  1. #101
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm realy not comfortable with having multiple transactions in the same session, as it _realy_ complicates some stuff if I wanna add automatic registerDirty() behavior.

  2. #102
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Just had a quick look, looks good so far.

    One thing that noticed was....

    $sql = str_replace('`',$this->escapeCharacter,$sql);

    in PDOProxy::query(), which means databases that are running as ANSI quote standard compliant (escapeCharacter would be ") means can never get a ` into the database.

  3. #103
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ren, actually - that's what i's for. It makes you able to write queries with ` and have them replaced with the escape char you want. And that only effects the query, not the values sent in.

  4. #104
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Ren, actually - that's what i's for. It makes you able to write queries with ` and have them replaced with the escape char you want. And that only effects the query, not the values sent in.
    Ah yes, unless the values are hardcoded in the SQL.

    As an aside, the way to escape names is..

    $escapedName = $this->escapeCharacter.str_replace($this->escapeCharacter, $this->escapeCharacter.$this->escapeCharacter, $name).$this->escapeCharacter;

    You can have a column named foo`bar, you'd have to be pretty insane todo it, but..

    Did put a feature request in for PDO to have a quoteName function, but got rejected :/

  5. #105
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, thanks for the heads up there :], I'll lock into hacking a regexp to do the proper replacing,

  6. #106
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Also if wanted to figure out the quote character automatically

    SELECT CASE FIND_IN_SET(\'ANSI_QUOTES\', @@global.sql_mode) WHEN 0 \'`\' ELSE \'"\' END quoteChar

    Would be the MySQL query.

  7. #107
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Damn where did you learn all this sql magic? ;p nah, I'll leave that up to the user to supply the correct escape character, thanks tho.

  8. #108
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, I released my ORM now, all information is available at the trac: http://model.serverside.se/trac/wiki/WikiStart, small tutorial + download links + api documentation.

  9. #109
    SitePoint Zealot
    Join Date
    Oct 2004
    Location
    Worcester
    Posts
    138
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Thanks thr and well done!

    Looking at it now...

  10. #110
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The bleeding edge version is always available from the svn at @ http://model.serverside.se:83/repos/

  11. #111
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Had a slight more indepth look, the API seems quite nice for doing simple operations, insert rows and what not.

    Tried to add sqlite support [as I like sqlite for just hacking about in], using an assumption that the first column of the table is PK, and using 'SELECT * FROM `$table` WHERE 1 = 0', to get the column names and types.

    But unfortunately if PDO returns no rows, you cant access the column metadata, which is pretty poor imo.

    After the extreme hack of making sure the table(s) have atleast one row, using SELECT * FROM `table` LIMIT 1, did actually get the basic operations working.

    PHP Code:
    protected function loadPDOTableInfo($type)
        {
            
    $type = (string)$type;
            if(isset(
    $this->tableInfo[$type]))
            {
                return 
    $this->tableInfo[$type];
            }
            else
            {
            
                
    $table call_user_func(array($type'__getTable'));
                
    $table is_null($table) ? $type : (string)$table;
            
                
    $this->tableInfo[$type] = array();
                
    $this->tableInfo[$type]['id'] = null;
                
    $this->tableInfo[$type]['keys'] = array();
                
    $this->tableInfo[$type]['fields'] = array();
                
    $this->tableInfo[$type]['table'] = $table;
                
    $this->tableInfo[$type]['types'] = array();
                
    $this->tableInfo[$type]['relations'] = call_user_func(array($type'__getRelations'));
                
                try
                {
                    
    $stmt $this->pdo->prepare("SELECT * FROM `$table` LIMIT 1");
                
                    
    $stmt->execute();
                
                    
    $n $stmt->columnCount();
                    for(
    $i 0$i $n; ++$i)
                    {
                        
    $meta $stmt->getColumnMeta($i);
                        
                        
    $this->tableInfo[$type]['types'][$meta['name']] = $meta['native_type'];
                                    
                        if (
    $i === 0)    
                        {
                            
    $this->tableInfo[$type]['id'] = $meta['name'];
                            
    $this->tableInfo[$type]['keys'][] = $meta['name'];
                        }
                        else
                        {
                            
    $this->tableInfo[$type]['fields'][] = $meta['name'];
                        }
                    }
                                    
                    if(
    count($this->tableInfo[$type]['keys']) == 0)
                    {
                        throw new 
    RuntimeException('Could not load info for table "'.$table.'" no keys in table.');
                    }
                    elseif(
    count($this->tableInfo[$type]['keys']) == && is_null($this->tableInfo[$type]['id']))
                    {
                        
    $this->tableInfo[$type]['id'] = $this->tableInfo[$type]['keys'][0];
                    }
                    return 
    $this->tableInfo[$type];
                }
                catch(
    RuntimeException $e)
                {
                    unset(
    $this->tableInfo[$type]);
                    throw new 
    RuntimeException("Could not load info for tabel '$table', caught exception of type: " get_class($e) . " with message: '" $e->getMessage() . "'");
                }
            }
        } 
    PS also posted a ticket on trac for some undefined variables.

  12. #112
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Oh, thank you Ren I'm doing some redesign in the internal stuff, etc. and alpha 0.1 is well... alpha 0.1 so.

    I'm going to try to move to a more object-centric approach then the current sql-centric approach, how would you(and all others) that are familiar with orms feel about that? (not hiding sql in any way, just well... more of an "object"-feel and less of a "object-mixed-with-sql"-feel").

    The current code (alpha 0.1) also holds some nasty bugs, etc - which I gotta sort out . Also trying to get a better "flow" of the codebase in the next release which will differ quite much from alpha 0.1 (inheritance should be in for once, more object-centric as I already mentioned).

  13. #113
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Arrow

    To well, explain my more "object"-centric approach idea, here's an example:
    PHP Code:
    <?php
    class Person
    {

        public 
    $name;
        public 
    $email;
        public 
    $age;
        public 
    $groups;
        
    }
    ?>
    The above also works with set/get:ers and protected properties but for simplicty I used public properties here

    Then to save your object to the database - you have two choices:
    1. Let Model try to auto-discover your datatypes (if you're lazy and only need float/integer/string)
    2. Give model a "template" object which it will use to create the tables - such as:

    PHP Code:
    <?php
    $tpl
    = new Person;
    $tpl->name    Model::string(25);
    $tpl->email    Model::string(100);
    $tpl->age      Model::int(3);
    $tpl->groups  Model::collection("Group"); /* Yes N:M relations will be possible, altho I'll always advice against it */
    $model Model::getInstance("default");
    $model->setTemplate($person);
    ?>
    So basicly, If you don't want to you have no need to create any SQL, Jointables, etc. at all - you create your objects, feed model a "template" object the first time you try to insert one object(these templates can be saved in %ModelAppDir%/templates/ and be autosensed, say Person.php for objects of type Person).

    It will be able to map inheritance properly(I hope) and my "ObjectQuery"(which I've yet to get a better name) will be able to handle polymorphism.

  14. #114
    SitePoint Zealot
    Join Date
    Oct 2004
    Location
    Worcester
    Posts
    138
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've also started playing with it - trying to get the tests to work into MSSQL

    I've started hacking together a Metadata::loadMSSQLTableInfo() function. However, learning how to get MSSQL to tell me about the meta data is taking more reading of the online book than I expected! I've also got a set of unitTests/sql/mssql_XXX.txt files that seem to work ok.

  15. #115
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm.. from what you two are telling me you like the current approach I've got in Model Alpha 0.1 ? How would the people that tested the current Alpha 0.1 feel about moving into a more "object" approach in the one I described two posts above?

  16. #116
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Think prefer the template object idea from above, removes some cruft (__getRelations() etc) from the domainobject classes.

    Also I think I'd like the idea of using some sort of Container. (see picoContainer, phemto) for registering DomainObjects, and handing that to the model for it to instance them. But I just maybe going overboard with Containers atm, as introduced them into my Routes solution, and doing stuff like

    PHP Code:
        // Just so we get the arguments described
        
    class PDOEx extends PDO
        
    {
            function 
    __construct($dsn$user ''$password '')
            {
                
    parent::__construct($dsn$user$password);
            }
        }
            
        
    $container = new Container();   

        
    /* Read application configuration, and setup container.... registerCached means this container will only create it once, and cache the object, sort of singleton with respect to this container.
    */
        
    $container->registerCachedComponent('PDO''PDOEx', array('dsn' => 'sqlite:test.sql3'
                                                                
    'user' => '',
                                                                
    'password' => ''));
        
    $container->registerCachedComponent('PDOHelper''PDOHelper', array('escapeCharacter' => '"'), 'Model/PDOHelper.php');
        
    $container->registerCachedComponent('Model''Model', array('classpath' => ''), './Model.php');
        
       
    // Allows for lazy creation so later in application can retrieve the Model, and it'll build the object tree (PDOEx, PDOHelper, & Model)
        
    $model $container->getInstance('Model'); 

  17. #117
    SitePoint Zealot
    Join Date
    Oct 2004
    Location
    Worcester
    Posts
    138
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Hmm.. from what you two are telling me you like the current approach I've got in Model Alpha 0.1 ? How would the people that tested the current Alpha 0.1 feel about moving into a more "object" approach in the one I described two posts above?
    I haven't played enough to have a preference. I quite like the idea about the templates though.

  18. #118
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, currently something like this works (for the more object centric approach):

    classes/Person.php
    PHP Code:
    <?php
    class Person implements Persistable
    {

        public 
    $name;
        public 
    $email;
        public 
    $age;
        public 
    $groups;
        
        protected 
    $parent;
        protected 
    $savings;
        
        public function 
    setParent($val)         { $this->parent $val; }
        public function 
    getParent()                { return $this->parent; }
        public function 
    setSavings($savings)    { $this->savings = (double)$savings; }
        public function 
    getSavings()             { return $this->savings; }
        public function 
    getNameEmailLink()         { return "<a href='mailto{$this->email}'>{$this->name}</a>"; }
        
    }
    ?>
    templates/Person.php:
    PHP Code:
    <?php
    $template 
    = new ModelClassMap("Person");
    $template->name        Model::stringField(10);
    $template->email    Model::stringField(25);
    $template->age        Model::integerField(3);
    $template->groups    Model::collectionField("Group");
    $template->setSavings(Model::doubleField(100));
    $template->setParent(Model::objectField("Person"));
    ?>
    test.php:
    PHP Code:
    <?php
    require 'classes/Person.php';
    require 
    'templates/Person.php';

    $person = new Person;
    $person->name "thr";
    $person->email "thrthr@gmail.com";
    $person->age 20;
    $person->groups = array();
    $person->setSavings(0.0);
    $person->setParent(new Person);

    $template->validateObject($person);
    ?>
    Say if you changed age to this:
    PHP Code:
    <?php
    $person
    ->age "20";
    ?>
    It would throw an Exception saying that age does not pass validation. It's also possible to build "custom" datatypes and use them instead, say you could build a custom datatype called Dollar, which would require a format such as '~^[\d\.]+\$$~' (expressed in regexp), extend it from the ModelStringField and changed the validate() method, voila. And it will ofc. be saved to the database (as string ofc, tho.)

    From these maps I'm also able(or will be when the code works ;p) to generate database tables, link tables, and such.

  19. #119
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    What about constraints that involve multiple fields? Perhaps have a collection of them on the template?

    Also would need somewho to identify when a field can hold a NULL value. Think lastcraft posted an idea of using a fluent style interface for defining table structures, which might be good.

  20. #120
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Say if you changed age to this:
    PHP Code:
    <?php
    $person
    ->age "20";
    ?>
    It would throw an Exception saying that age does not pass validation.
    Hmm.. not too sure about that. I say I'm not sure because incoming data is always a string datatype.

    If the model knows that age should be an integer, then why not instead automatically cast it as an integer before validating?

    I dunno, it just seems throwing an Exception like that because it is a string doesn't fit very well with PHP's type juggling. I think auto casting would better fit because then you could still keep strict guidelines for the properties, but not loose type juggling.

  21. #121
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm I think keep the base types as rigid as possible. Can always create a custom type todo more type juggling.

  22. #122
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    Hmm I think keep the base types as rigid as possible. Can always create a custom type todo more type juggling.
    I'm not saying take that away.

  23. #123
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by dreamscape
    Hmm.. not too sure about that. I say I'm not sure because incoming data is always a string datatype.
    You know what happends when you quote a string with PDO::quote() ? It get's " around it, I know MySQL can take strings as integers, but asfar as I can tell no other DB does that(and I for one think MySQL is wrong doing that).

    Quote Originally Posted by dreamscape
    If the model knows that age should be an integer, then why not instead automatically cast it as an integer before validating?
    Because if it is a string but should be a integer, it's invalid data.

    For this example you can just as well do:
    PHP Code:
    <?php
    class Person
    {
     
    /* ... */
      
    setAge($age){ $this->age = (int)$age; }
      
    getAge() { return $this->age }
     
    /* ... */
    }
    ?>
    And keep Person::$age protected/private. You won't ever get a conflict with the DB and the data is always correct.


    Quote Originally Posted by Ren
    What about constraints that involve multiple fields? Perhaps have a collection of them on the template?
    Hmm... not following you here... how do you mean constrains on multiple fields?

    Quote Originally Posted by Ren
    Also would need somewho to identify when a field can hold a NULL value. Think lastcraft posted an idea of using a fluent style interface for defining table structures, which might be good.
    Agreed, might add a second parameter in the constructor, something like:
    PHP Code:
    <?php
    class ModelClassField
    {
         
    /* ... */
         
    public function __construct($type$allownull false){
         
    /* ... */
    }
    ?>
    Quote Originally Posted by Ren
    Think lastcraft posted an idea of using a fluent style interface for defining table structures, which might be good.
    Hmm.. interesting, where?

    Edit: A thing I need advice on currently his how to do with the set/getMethods(), as currently the ModelClassReflector (wraps the ReflectionClass + ReflectionProperty + ReflectionMethod classes in a nicer interface just) looks for two methods that have the same name except the set/get prefix. Is this sufficent or should I look for a protected/private property named with the same name as the methods (w/o the prefix of set/get ofc.) ?

  24. #124
    SitePoint Wizard dreamscape's Avatar
    Join Date
    Aug 2005
    Posts
    1,080
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    You know what happends when you quote a string with PDO::quote() ? It get's " around it, I know MySQL can take strings as integers, but asfar as I can tell no other DB does that(and I for one think MySQL is wrong doing that).
    You've completely missed what I was saying.

    Quote Originally Posted by thr
    Because if it is a string but should be a integer, it's invalid data.
    That's ridiculous. All user data is a string. You're saying that all user data that you want to be something other than a string is inherently invalid. It is inherently untrustworthy, but that doesn't make it inherently invalid just because PHP reads it in as a string and not an integer. That's absurd, and pretty much flies right in the face of how PHP deals with types.

    There's no logical reason that you shouldn't be able to do $person->age = '24'; and have it automatically mapped as an integer.

    Let me put this another way... what exactly is the purpose of having datatypes in the model map templates, if you have to manually map the datatypes anyways?

  25. #125
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    Hmm.. interesting, where?
    http://www.sitepoint.com/forums/show...48&postcount=1

    Though I remembered that looking alot nicer.

    Quote Originally Posted by thr
    Edit: A thing I need advice on currently his how to do with the set/getMethods(), as currently the ModelClassReflector (wraps the ReflectionClass + ReflectionProperty + ReflectionMethod classes in a nicer interface just) looks for two methods that have the same name except the set/get prefix. Is this sufficent or should I look for a protected/private property named with the same name as the methods (w/o the prefix of set/get ofc.) ?
    Just the methods is probably good enough, another possibility with 5.1 is use Reflection*::getDocComment() and use a marker keyword in that.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •