WordPress.org

Ready to get started?Download WordPress

Forums

Posts 2 Posts
How To Add Info to Connection (78 posts)

  1. Derek Perkins
    Member
    Posted 3 years ago #

    I'm not sure that this is possible with a taxonomy, but I was hoping to get some feedback on the best way to store my data. My site is storing information about soccer players and teams. I have a team custom post type and a player custom post type. My team page shows all of the related players, based on Posts to Posts data previously entered.

    My problem is that in the future, when players change teams, there isn't any way to store any kind of time related data with the existing relationship. For example, at a minimum, I'd love to be able to store some sort of tag 'current', so that way my team page could show the current team as well as a list of all players. Even better would be storing the years that a player was a part of the team.

    I was thinking that perhaps the taxonomy description would be a place to store that information without having to create new tables or fields. I could maybe serialize some information and put it in as part of the connection process. Does that sound like a good way to accomplish what I'm trying to do? The API might then be changed to have an optional filter based on the information stored in the description.

    While I'm writing this, I'm still brainstorming how to make it functional. I'm thinking that in P2P metabox, after you create a connection, there could be a little button added that would allow you to edit the relationship description. That wouldn't require much of an interface than a text area, and you just assume that the developer putting data in there would also know how to read it out.

    I haven't looked super closely at the actually hidden taxonomy, so it might not even be feasible given the current setup. Thoughts?

  2. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    I was thinking that perhaps the taxonomy description would be a place to store that information without having to create new tables or fields. I could maybe serialize some information and put it in as part of the connection process. Does that sound like a good way to accomplish what I'm trying to do? The API might then be changed to have an optional filter based on the information stored in the description.

    It would be really hackish, because there's only one description field per term (i.e. post). You would be better of storing the data as custom fields on one side or the other.

    For example, you could make the Team post type hierarchical. There would be a parent team post, where you store the permanent data, like founding date, description etc. Each parent post would have child posts which connect to players. Whenever a player comes or goes, a new child post would be created with the new team configuration.

    Another way would be to have a third post type, dubbed "Connection" or something, which would act as a bridge between a team and a player.

  3. Derek Perkins
    Member
    Posted 3 years ago #

    Thanks for the advice. I'm actually going to end up using both of your suggestions for different parts of the site. I'm going to make my teams hierarchical like you said. I'm also keeping track of which players are wearing which shoes, so I'm going to create a player-shoe custom post type as the bridge between them. Thanks!

  4. Derek Perkins
    Member
    Posted 3 years ago #

    Now that I'm knee deep in the in-between post type, I'm running into a couple issues, mainly with scalability. Here are the three post types and how they are connected with P2P.

    soccer-shoes <-> connection <-> soccer-players

    If I'm on a soccer-shoe, I can call p2p_get_connected( $post_id, 'both', 'connections', 'objects' ); The potential issue is that I will then have to then loop through all the connections to that shoe, which could be a ton, then call p2p_get_connected( $loop_post_id, 'both', 'soccer-players', 'objects' ); on each of the objects in the array.

    Would it be more efficient if I built a custom SQL query to pull out everything related?

  5. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    Would it be more efficient if I built a custom SQL query to pull out everything related?

    Yes, it would, but given the complicated schema of the taxonomy system, it would not be trivial to write.

    I have to concede that a custom db table would be the best solution in this case. Something like this:

    post_a int(20) NOT NULL
    post_b int(20) NOT NULL
    connection int(20) NOT NULL default 0
    UNIQUE KEY (post_a, post_b, connection)

    The 'connection' column would point to a post id that contains extra data about the connection. It's the same idea as before, but with a better db layout.

  6. Derek Perkins
    Member
    Posted 3 years ago #

    Alright, I tried for hours before succeeding, but I eventually won. Here is a function that will return connected posts. Here are the caveats to this approach.

    1. I had to edit all the p2p terms table entries to remove the 'p' prefix
    2. I also then had to edit the p2p core.php file to stop the convert function from adding / looking for the 'p' prefix

    This function will return all posts of a certain type given the starting post's ID, the custom post type in the middle that we are connecting through, and the custom post type that we are looking for.

    In my case, this is how it works.
    soccer-shoes <-> connection <-> soccer-players

    $related_objects = p2p_get_connection_via_connection( 30, 'connection', 'soccer-players' );
    
    function p2p_get_connection_via_connection( $post_id, $post_type_b, $post_type_c )
    {
    	global $wpdb;
    
    	$sql = "SELECT p.post_title, cp.post_title, ccp.post_title
    	  FROM sr_terms t
    		INNER JOIN sr_term_taxonomy tt ON t.term_id = tt.term_id
    		INNER JOIN sr_term_relationships tr ON tr.term_taxonomy_id = tt.term_taxonomy_id
    		INNER JOIN sr_posts p ON tr.object_id = p.ID
    		INNER JOIN sr_posts cp ON t.name = cp.ID
    		INNER JOIN sr_term_relationships ctr ON cp.ID = ctr.object_id
    		INNER JOIN sr_term_taxonomy ctt ON ctr.term_taxonomy_id = ctt.term_taxonomy_id
    		INNER JOIN sr_terms ct ON ctt.term_id = ct.term_id
    		INNER JOIN sr_posts ccp ON ct.name = ccp.ID
    	  WHERE p.ID = $post_id
    		AND cp.post_type = $post_type_b
    		AND ccp.post_type = $post_type_c";
    
    	$connected_posts = $wpdb->get_results( $sql );
    
    	return $connected_posts;
    }

    I have a few questions for you.

    • Is there a problem with not having the 'p' prefix?
    • I only removed the 'p' prefix from the name column, not the slug column. Will that cause issues if they are different?
    • What do you feel about including this in the core of P2P? Obviously some error checking should be added to my function above, but I think it makes sense.

    In any case, thanks for your great plugin to work with.

  7. Derek Perkins
    Member
    Posted 3 years ago #

    After digging around a little more, I made a couple other changes. I tried changing the slug to match the name, but that didn't work because there were conflicts with matching slugs. I didn't clarify above, but the reason that I had to remove the 'p' prefix from the name column above was so that I could perform an INNER JOIN on it and the posts table.

    Since the slugs weren't changing, I changed the get_connected function in core.php to get terms by the name and not the slug.

    FROM
    $term = get_term_by( 'slug', reset( self::convert( 'term', $post_id ) ), self::TAX );
    TO
    $term = get_term_by( 'name', reset( self::convert( 'term', $post_id ) ), self::TAX );
  8. Derek Perkins
    Member
    Posted 3 years ago #

    Also, if you're interested in testing what I did, here is the SQL code to remove the 'p' prefix from the name column.

    UPDATE sr_terms t
    INNER JOIN sr_term_taxonomy tt ON t.term_id = tt.term_id
    SET t.name = SUBSTRING(t.name FROM 2)
    WHERE tt.taxonomy = "p2p"
  9. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    That's a lot of inner joins! It's precisely the reason I suggested a custom table. I will probably rewrite my plugin (again) with that schema.

    Still, I admire your persistence. :)

    Is there a problem with not having the 'p' prefix?

    I added the 'p' prefix to avoid subtle errors: the taxonomy API acts differently when you pass it ints vs. strings.

  10. Derek Perkins
    Member
    Posted 3 years ago #

    That sounds great. A custom table would definitely improve performance. Any idea when you might get around to rewriting the plugin? I'm in the process of inputing potentially tens of thousands of links for my site, so having it set up would put my mind at ease.

    Also, if I can make a suggestion on the rewrite, it would be great if there was a good way to edit the connection details right from that screen. With the custom table setup, it shouldn't be necessary to ever have an in-between custom post type, depending on how you choose to store the connection.

  11. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    With the custom table setup, it shouldn't be necessary to ever have an in-between custom post type, depending on how you choose to store the connection.

    Indeed. I was thinking of adding a p2p_meta table that could store arbitrary data about each connection.

    Also, if I can make a suggestion on the rewrite, it would be great if there was a good way to edit the connection details right from that screen.

    There will be no UI for editing connection details, since it's arbitrary data, as I've mentioned above. However, I will make it easy enough to extend the existing metabox.

    Any idea when you might get around to rewriting the plugin?

    I've already started, but don't know when I'll finish.

  12. Derek Perkins
    Member
    Posted 3 years ago #

    I'm excited for the future of this plugin. I'm willing to help where needed. Adding a p2p_meta table is definitely worth doing.

    However, I will make it easy enough to extend the existing metabox.

    Being able to extend the box is great. I started writing some code to help make the extra cpt easier to make, but I had to hack into the admin.php file to do it.

  13. Derek Perkins
    Member
    Posted 3 years ago #

    Is there anything I can do to help with the further development of this plugin? The ability to link posts together is vital to my website, so this plugin is very important to me.

  14. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    There's a new development version (0.4-alpha4) available.

    The best way to help is to test the hell out of it. Don't forget to re-activate the plugin after updating.

    Notes:

    • the code to migrate the data from the taxonomy isn't written yet
    • most functions in the api.php file have an extra $data parameter. ;-)
  15. Derek Perkins
    Member
    Posted 3 years ago #

    You rock. Do I need to run an update like previous upgrades?

  16. Mike Schinkel
    Member
    Posted 3 years ago #

    Hi Ploobers,

    Would love if you would comment on this Trac ticket.

    http://core.trac.wordpress.org/ticket/14513

    I proposed the need for a table in WordPress core to address these kind of use-cases but several developers said that most people would not need it and thus called is an "edge case". If you think it is not an edge case, maybe your voice would help.

    -Mike

  17. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    You rock. Do I need to run an update like previous upgrades?

    1. Download the development version again.
    2. De-activate & re-activate

    The tables should be created.

  18. Derek Perkins
    Member
    Posted 3 years ago #

    I'm just getting a chance to look through this now. Do we not declare whether or not the connection is reciprocal anymore?

  19. Derek Perkins
    Member
    Posted 3 years ago #

    'box' string A class that implements the P2P_Box interface. Default: P2P_Box_Multiple
    I'm glancing through the API and looking at the registration parameters. I'm assuming that this is how we are going to extend the connection box, correct? I didn't see that code included in the alpha 4 release, so is that coming soon?

  20. Derek Perkins
    Member
    Posted 3 years ago #

    Sorry, my bad, just found it in the ui.php.

  21. Derek Perkins
    Member
    Posted 3 years ago #

    I've been working for the last couple hours on extending the metabox and I've got a couple of questions / ideas.
    -Removing metadata - Should metadata be automatically be deleted upon disconnect?

    Here's a sample of the code I am adding to the p2p box. I want to add a start and end date to each connection that I am making. I copied the P2P_Box_Multiple class to my functions.php file and renamed it to a new class. Inside the loop that adds the connected item checkboxes, I added these two date fields.

    echo "Start Date:<input class='sr_datepick' id='start_date_$id' type='text' size=7>";
    echo "End Date:<input class='sr_datepick' id='end_date_$id' type='text' size=7>";

    I want to save that data, but I am looking through the save function and I can't figure out how to get the p2p id, so I can't see how to use the add_p2p_meta function.

    What would be the best way to tie into the update to save that metadata?

  22. Derek Perkins
    Member
    Posted 3 years ago #

    Multiple connections to the same post:
    Here is a potential situation I might be facing. What if I want to have multiple connections to the same post? In my case, it might be a sponsored player. Maybe someone was sponsored by Nike from 2001-2004, by Adidas from 2005-2009, and in 2010 switched back to Nike again. That should be possible now with the table setup, correct?

  23. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    Do we not declare whether or not the connection is reciprocal anymore?

    No, I didn't like how data was duplicated. You can register a metabox with reversed parameters if you want to be able to edit connections from both sides.

    Removing metadata - Should metadata be automatically be deleted upon disconnect?

    Yes, it should, and it is.

    I want to save that data, but I am looking through the save function and I can't figure out how to get the p2p id, so I can't see how to use the add_p2p_meta function.

    You can use p2p_connect():

    p2p_connect($from, $to, array(
      'start_date' => $_POST["start_date_$id"],
      'start_date' => $_POST["end_date_$id"]
    ));

    Note: Should probably do some validation first.

    Multiple connections to the same post

    Yes, it is possible, as long as the metadata is different.

  24. Derek Perkins
    Member
    Posted 3 years ago #

    No, I didn't like how data was duplicated. You can register a metabox with reversed parameters if you want to be able to edit connections from both sides.

    So assuming that you register the reverse metabox, will it show connections that were made from the other direction?

    Multiple connections to the same post: Yes, it is possible, as long as the metadata is different.

    The UI currently doesn't allow you to add multiple connections to the same post.

    Hooks
    I like the metabox idea, but I was also thinking about potentially adding some hooks into the default P2P_Box_Multiple. Basically, I think most users would just want to be able to hook into the loop where I did, since they will be saving data for each connection. That would keep the majority of people from having to copy a whole extra class out and would make upgrades significantly easier in the future.

  25. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    So assuming that you register the reverse metabox, will it show connections that were made from the other direction?

    I'll just add the 'reciprocal' parameter back, which will take care of the whole thing.

    I like the metabox idea, but I was also thinking about potentially adding some hooks into the default P2P_Box_Multiple.

    I think it's too early for that, but I'm not against the idea.

  26. Derek Perkins
    Member
    Posted 3 years ago #

    I'm running into some problems with my metabox. I'm trying to save my metadata. I replaced your p2p_connect with this loop.

    foreach ( array_diff( $new_connections, $old_connections ) as $nc ) {
    	$start_date = $_POST[ 'start_date_' . $nc ];
    	$end_date = $_POST[ 'end_date_' . $nc ];
    	$data = array( "start_date" => $start_date, "end_date" => $end_date );
    	p2p_connect( $post_a, $nc, $data );
    }

    If I run the code above, the metadata can only be inserted when the connection is initially made, because it won't run the connect code afterwards.

    foreach ( $new_connections as $nc ) {
    	$start_date = $_POST[ 'start_date_' . $nc ];
    	$end_date = $_POST[ 'end_date_' . $nc ];
    	$data = array( "start_date" => $start_date, "end_date" => $end_date );
    	p2p_connect( $post_a, $nc, $data );
    }

    If I run this loop, it connects the post again every time the post is updated. My metadata is inserted correctly, but with a new p2p_id each time the update is called.

    Once I disconnect the posts, it deletes ALL of the metadata. If there are multiple connections, it should only delete the metadata for that specific connection.

    Maybe I'm missing something in the API, but it seems to me that the p2p_id field needs to be added to the metabox that I can use as a variable. That will solve two problems.
    1) That will be necessary in order for the UI to be able to have multiple connections to the same post.
    2) I can update the post meta directly, so that it can be changed after the connection is originally made.

    Hook Implementation
    I think hooks would be the best way to deal with this, by hiding core functionality and making P2P much more accessible to the average developer. I think that you could get by with making three hooks available.
    1) box: Insert an action hook inside the existing loop per displayed connection. You can insert form fields here or a link to an AJAX form or something if you have more intense connection details.
    2) save: Have a save loop similar to what I have proposed here, with a filter hook that lets you edit the $data parameter based on a p2p_id variable.
    3) load: I haven't look much at this, but you'd need a similar hook to the save function in here to let you display your data.

  27. Derek Perkins
    Member
    Posted 3 years ago #

    I'll just add the 'reciprocal' parameter back, which will take care of the whole thing.

    Even with reciprocal data, you shouldn't have to duplicate the information again. You could just add an extra boolean field to the table that is 'reciprocal', then alter the get connected SQL query to look at both fields.

  28. scribu
    Member
    Plugin Author

    Posted 3 years ago #

    development version (0.4-alpha5):

    The 'reciprocal' arg is back. Instead of adding an extra field to the table, I added a $reversed flag to the P2P_Box_Multiple class.

    You can use the $this->box_id variable to differentiate between boxes.

    Once I disconnect the posts, it deletes ALL of the metadata. If there are multiple connections, it should only delete the metadata for that specific connection.

    You have to pass $data to p2p_disconnect() too.

    Maybe I'm missing something in the API, but it seems to me that the p2p_id field needs to be added to the metabox that I can use as a variable.

    p2p_get_connected() now returns array(p2p_id => post_id).

    PS: I think you'll find the changelog useful.

  29. Derek Perkins
    Member
    Posted 3 years ago #

    I'm working on this again, but my feeling as I'm diving through the code again is that this is far too technical for typical usage. To try and figure out what kind of data I'm supposed to pass into the $data argument, I'm having to follow your function changes through the boxes.php, api.php and storage.php files, and I'm still not quite sure what to pass and what the best method is for storing connection specific data.

  30. Derek Perkins
    Member
    Posted 3 years ago #

    Could you provide an example for how to store a single piece of metadata per connection?

Topic Closed

This topic has been closed to new replies.

About this Plugin

About this Topic