Coder Social home page Coder Social logo

equalnestbehavior's Introduction

EqualNestBehavior

Build Status

The EqualNestBehavior is inspired by Doctrine's Equal Nest Relations implementation, and provides a way to define relations between objects that have equal hierarchy - think about a person and his friends.

Requirements

This behavior requires Propel >= 1.6.0.

Installation

Get the code by cloning this repository, or by using Composer (recommended):

{
    "require": {
        "craftyshadow/propel-equalnest-behavior": "~1.2"
    }
}

Then, if you don't use Composer, or an autoloader in your application, add the following configuration to your build.properties or propel.ini file:

propel.behavior.equal_nest.class = vendor.craftyshadow.propel-equalnest-behavior.src.EqualNestBehavior

Note: vendor.craftyshadow.propel-equalnest-behavior.src.EqualNestBehavior is the path to access the EqualNestBehavior class in "dot-path" notation.

Then declare the behavior in your schema.xml:

<table name="person">
  <column name="id" required="true" primaryKey="true" autoIncrement="true" type="INTEGER" />
  <column name="name" type="VARCHAR" required="true" />
</table>

<table name="friend">
  <behavior name="equal_nest">
    <parameter name="parent_table" value="person" />
  </behavior>
  <!-- you do not need to specify any colums for the "friend" table, the behavior will add them automatically -->
</table>

Setup with symfony 1.4

Copy the behavior to lib/vendor/equal_nest_behavior and then register the behavior class by adding the following to the bottom of the config/propel.ini file:

; check that you have behaviors enabled
propel.builder.addBehaviors = true

; and add the custom behavior
propel.behavior.equal_nest.class = lib.vendor.equal_nest_behavior.EqualNestBehavior

Then in your schema.yml:

propel:

  person:
    id: ~
    name: { type: varchar(255) }

  friend:
    _propel_behaviors:
      symfony: { form: false, filter: false }
      equal_nest:
        parent_table: person
    # you do not need to specify any columns for the "friend" table, the behavior will add them automatically

Usage

Continuing with the example above, here is how you would use the Person object to define Friend relationships:

<?php

$john  = new Person();
$peter = new Person();
$marry = new Person();

$john->addFriend($peter);
$john->addFriend($marry);
$john->addFriends(array($peter, $marry)); // same as the above

$john->getFriends(); // returns a PropelObjectCollection ($peter, $marry)

$john->hasFriend($peter); // true
$peter->hasFriend($john); // true

$john->removeFriends();
$john->getFriends(); // empty array
$john->save(); // commit to the DB

The most important thing to remember is that all changes are committed to the database only after you call the ->save() method!

Also, keep in mind that relations are non-transitional:

<?php
$john->addFriend($marry);
$marry->addFriend($peter);
$john->hasFriend($peter); // false

If you need this you will have to manually implement it.

ActiveRecord API

<?php

$person->addFriend($friend);

$person->hasFriend($friend);

// get all friends, will be cached if no citeria specified. Filtered by the criteria otherwize
$person->getFriends($criteria = null, $con = null);

// replace the current collection of friends
$person->setFriends($friends_array);

// append to the current collection of friends
$person->addFriends($friends_array);

// remove a specfic friend
$person->removeFriend($friend)

// remove all friends
$person->removeFriends();

$person->countFriends($criteria = null, $distinct = false, $con = null);

ActiveQuery API

<?php

PersonQuery::create()->findFriendsOf($person, $con = null);

PersonQuery::create()->countFriendsOf($person, $con = null);

Parameters

<behavior name="equal_nest">
    <parameter name="parent_table"       value="person" />
    <parameter name="reference_column_1" value="friend_1" />
    <parameter name="reference_column_2" value="friend_2" />
</behavior>

Propel pluralizer

This behavior makes use of the Propel pluralizer when generating the relational interface. Make sure to always use the StandardEnglishPluralizer bundled with Propel 1.6 and up whenever possible (eg when you are starting a new project).

To use the better pluralizer add the following to your build.properties (for standalone Propel) or propel.ini (for symfony + Propel):

propel.builder.pluralizer.class = builder.util.StandardEnglishPluralizer

Running tests

Install dependencies:

php composer.phar install --dev

Run the test suite:

phpunit

License

This behavior is released under the MIT License. See the bundled LICENSE file for details.

equalnestbehavior's People

Contributors

lionelbzv avatar martiusweb avatar mattleff avatar vantanev avatar willdurand avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

equalnestbehavior's Issues

compatibility with versionable behavior?

isVersioningNecessary does not seem to consider the methods used by the EqualNest behavior, thus a new version is NOT created when adding "friends" to any given "person" object. The data in the array type columns (such as "person_friend_ids" and "person_friend_versions") created by Versionable behavior in the "version" table, is out of phase with the insertion of "friends". "friends" are only added to the version table in a subsequent version to the one they were actually inserted, since it is only until the execution of methods like "getPersonFriendRelatedByPersonId()" that the data is stored in the dedicated columns of the "version" table.

Cannot save objects on a read-only model

With:

<table name="friend">
  <behavior name="equal_nest">
    <parameter name="parent_table" value="user" />
  </behavior>
</table>

And:

    $user = new User();
    $user->save();

    $friend = new User();
    $friend->save();

    $user->addFriend($friend);
    $user->save();

I see: "Cannot save objects on a read-only model" -- vendor/propel/runtime/lib/collection/PropelObjectCollection.php at line 28

Backtrace:

1:
at PropelObjectCollection ->save ()
in Model/om/BaseUser.php at line 2430 -+
2:
at BaseUser ->processEqualNestQueries (object(DebugPDO))
in Model/om/BaseUser.php at line 1049 -+
3:
at BaseUser ->save ()
in mycode.php at line 679 -

This would be really useful if it was working - I saw a message here: propelorm/Propel#127 that your Behavior might have been broken since Propel 1.6.2?

setup travis-ci

Heya @craftyshadow,

Could you please enable the travis-ci hook for this repo, so that we can have continuous integration for this behavior.

Cheers!
William

Infinite loop when adding friends

I have a dummy file that inserts random data in to my database to test a system. One part of it is causing the system to hang. See the following code:

$users = UserQuery::create()->find();
foreach ($users as $user){
  $limit = rand(1,count($users)-1);
  $c = new Criteria();
  $c
    ->setLimit($limit)
    ->addAscendingOrderByColumn('rand()')
    ->add('Id', $user->getId(), Criteria::ALT_NOT_EQUAL);
  $randomFriends = UserPeer::doSelect($c);

  $user->addFriends($randomFriends);
  $user->save();
}

This code will hang. From what I can see it's hanging when it reaches the save() function. The weird thing is that it always seems to hang when it reaches user ID 6 (there are 20, PKs in succession from 1 to 20).

Note that when I only add 1 friend (either in an array or just with addFriend() it seems to work fine, and quickly. Also, if I wrap the $user->save() in something like if ($user->getId() < 5) then that also works without hanging, and fairly quickly too. I can also pick higher numbers, not just the first few. The user data is also inserted randomly so it's not that.

What about unidirectional relations?

I tried to build a follower/followee relation. I have 2 tables, a user table and a cross-reference table called follower_followee.
The logic should be that a user can be a follower of another user who would be the followee. The problem is that the equalNestBehavior seems to build up bi directional relations, so if Alice follows Bob, Bob is automatically follower of Alice.
Is there a way to have it the correct way? Alice follows Bob, but Bob does not follow Alice only because of this?

Ensure each method is "strong"

This behavior is now pretty well tested, so it's time to add more tests to ensure each method is strong.
In other words, we should write tests, and use invalid data like null, 0, -1, etc...

Handling Schema is missing

Hi Ivan, Im trying to handle schema in Your behavior, but schema handling is not working when I have

<database schema="dd">

  <table name="test">
  <!-- ... -->
  </table>

  <table name="test_test" phpName="TestTest">
      <vendor type="mysql">
          <parameter name="Engine" value="InnoDB"/>
          <parameter name="Charset" value="utf8"/>
          <parameter name="Collate" value="utf8_polish_ci"/>
      </vendor>
      <behavior name="equal_nest">
          <parameter name="parent_table" value="test"/>
          <parameter name="reference_column_1" value="test_id"/>
          <parameter name="reference_column_2" value="test2_id"/>
      </behavior>
  </table>

</database>

after trying to rebuild my models, i get

Fatal error: Call to a member function getPrimaryKey() on a non-object in /.../vendor/craftyshadow/propel-equalnest-behavior/src/EqualNestBehavior.php on line 35

If I change

          <parameter name="parent_table" value="dd.test"/>

i get error

Execution of target "om-template" failed for the following reason: /.../vendor/propel/propel1/generator/build-propel.xml:538:56: Table "dd.test" contains a foreign key to nonexistent table "test"

Sorry about my english, hope you got it.

Greetings from Poland
skowron-line

SQLSTATE[HY093] on "initListMyObjectAssociatedsPKs"

Hi,

I just installed the behavior (with sf2.1 & propel 1.6.7 env) and encountered a problem in the "initListMyObjectAssociatedsPKs" method:

SQLSTATE[HY093]: Invalid parameter number
500 Internal Server Error - PDOException

It seems the bindValue doesn't work properly.

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.