最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - Find Site ID From WP_Post

programmeradmin5浏览0评论

Background

I am writing a migration tool that can move (copy, then delete) posts from one site on a multi-site network to another. I want to correctly separate concerns, and from that point of view it seems that in order to migrate a post from one site to another you need two things:

  1. The post - in WP represented by a WP_Post object.
  2. The site ID - ID of the site to migrate it to.

Question

How can I, being given only a WP_Post instance, get the ID of the site it belongs to?

Remarks

Foreseeing answers that just use get_current_blog_id(): that will get the ID of the current site, whatever that is. I want the ID of the site that the given post belongs to.

For those saying "if you're working with a post, you probably know where it came from, because you queried for it":

function doSomethingWithPost(WP_Post $post)
{
  // No, I do not know that
}

It appears that the WP_Post object does not contain the information necessary to track it to its site. Ticket #51373 raised in relation to this problem.

Background

I am writing a migration tool that can move (copy, then delete) posts from one site on a multi-site network to another. I want to correctly separate concerns, and from that point of view it seems that in order to migrate a post from one site to another you need two things:

  1. The post - in WP represented by a WP_Post object.
  2. The site ID - ID of the site to migrate it to.

Question

How can I, being given only a WP_Post instance, get the ID of the site it belongs to?

Remarks

Foreseeing answers that just use get_current_blog_id(): that will get the ID of the current site, whatever that is. I want the ID of the site that the given post belongs to.

For those saying "if you're working with a post, you probably know where it came from, because you queried for it":

function doSomethingWithPost(WP_Post $post)
{
  // No, I do not know that
}

It appears that the WP_Post object does not contain the information necessary to track it to its site. Ticket #51373 raised in relation to this problem.

Share Improve this question edited Sep 22, 2020 at 10:13 XedinUnknown asked Sep 21, 2020 at 14:57 XedinUnknownXedinUnknown 2521 silver badge7 bronze badges 9
  • 1 As far as I’m aware Posts don’t have a record of which site they belong to apart from the database table that they’re in. But it’s very unlikely that you’ve ended up with a WP_Post object without first knowing which site it belongs to. If you’re getting a WP_Post object then you must’ve queried the post somehow, and to do that you need to know which site to query, so you must already have a record of which site you’re getting the post from. Could you elaborate on the context where you’ve got a post object without knowing where it came from? – Jacob Peattie Commented Sep 21, 2020 at 15:23
  • > If you’re getting a WP_Post object then you must’ve queried the post somehow, and to do that you need to know which site to query, so you must already have a record of which site you’re getting the post from Nope. See updated question. – XedinUnknown Commented Sep 22, 2020 at 8:10
  • Your example still involves you sending the post to your function. It didn't come from nowhere. At some stage you must be retrieving the post from a known source, even if it's just the current site, so you should be able to pass that information alongside the post. – Jacob Peattie Commented Sep 22, 2020 at 8:37
  • No, it doesn't mean that. Have you heard of Separation of Concerns? I mention it in the question's Background. If I have a function that accepts a WP_Post, it doesn't meant that the code invoking that function is in the same package, or that it's under my control. – XedinUnknown Commented Sep 22, 2020 at 10:11
  • 1 Only in a circustantial sense, WP_Post objects are just data containers, they don't belong to anything, or provide any guarantees. E.g. there's no guarantee that a WP_Post object has a row in the database, you can do $p = new \WP_Post() or use a post object after the post is deleted. The APIs around post objects don't account for posts on any site other than what's considered current – Tom J Nowell Commented Sep 22, 2020 at 15:07
 |  Show 4 more comments

1 Answer 1

Reset to default 1

No, post objects do not store this data. You need to store the site ID separately.

Post objects do not store the site they were created on or are currently hosted on. That information doesn't exist in the posts table, nor does WordPress track it elsewhere. The assumption is always that the post comes from the current site.

The code you're writing will need to store the source site ID somehow. Some plugins do this via post meta.

If you already have posts that have been migrated though, would have to load up each site, and query for the post with the same ID, then compare them, and if they match, you've found it. This assumes no modifications have been made at either end.

Q: How do we know this?

Because there is nowhere in WP_Post that stores the site ID or network ID. Inspecting a variable holding a post object shows this information isn't available either.

Q: What do other plugins/developers do?

If they need to migrate a post to another site, but also need to trace it back to its source, they store those details in post meta.

For example, the original URL, site ID, and post ID can be stored as post meta. This is useful for UI purposes, telling a user that the post has been migrated or syndicated. This is what the syndicator and distributor plugins do.

Q: Can the GUID be used?

No, GUID's aren't always URLs, aren't always current, and don't always represent the source.

For example, a GUID will not change if a posts slug or URL changes, the GUID can be a hash not a URL, the GUID may be a remote URL, or it may be a URL from an old permalink structure or an old site URL.

Q: Do we need to get the site ID from a post object?

No! If you have a post object then at some point you were in the context of the site it came from. Pass the site ID as a second parameter.

Ideally, your function should receive a post ID and a site ID, not a post object:

function doSomethingWithPost( int $post_id, int $site_id=0 ) {
    switch_to_blog( $site_id );
    $post = get_post( $post_id );
    // ....
    restore_current_blog();
}

Or, the site should be assumed to be the current site, and switch_to_blog called beforehand, e.g.:

switch_to_blog( $site_id );
doSomethingWithPost($post_id);
restore_current_blog();

I recommend passing the site ID as a function parameter so that good dependency injection can be practiced.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论