Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ElementQuery::site/siteId: Allow multiple? #2854

Closed
timkelty opened this Issue May 7, 2018 · 20 comments

Comments

Projects
None yet
10 participants
@timkelty
Copy link
Contributor

timkelty commented May 7, 2018

Unless I'm missing something - it would seem it is impossible to select elements from multiple sites with ElementQuery.

Both site and siteId seem to only accept scalar values, and passing null seems to only select the default/current site elements.

Craft CMS 3.0.5

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented May 7, 2018

Correct. I guess I should take this as a feature request?

@khalwat

This comment has been minimized.

Copy link
Contributor

khalwat commented May 7, 2018

It'd be nice to be able to pass in null to get Elements from all sites that match the criteria, or to be able to pass in the site or siteId as an array, imo

@timkelty

This comment has been minimized.

Copy link
Contributor Author

timkelty commented May 8, 2018

Correct. I guess I should take this as a feature request?

Yep, guess so.
I wasn't 100% of the intended behavior given then description of the site param (the site(s)’s part):

Sets the siteId param based on a given site(s)’s handle

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented May 8, 2018

Doh, that is a doc bug; fixed for the next release. Just as you couldn’t select elements from more than one locale in Craft 2, you can’t (currently) select elements from more than one site at a time in Craft 3. Will look into what it would take to change that, though.

@bartrylant

This comment has been minimized.

Copy link

bartrylant commented Nov 20, 2018

This request was posted in May. Is it being developed or do I need to look for other solutions to solve this problem?

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented Nov 20, 2018

Not currently being developed, no.

@Harry-Harrison

This comment has been minimized.

Copy link

Harry-Harrison commented Nov 21, 2018

I proposed the ideas on my accidental duplicate of the following.

Entry::find()
    ->section('businesses')
    ->site(['siteHandle1', 'siteHandle2', 'siteHandle3'])
    ->orderBy('title asc')
    ->limit(100)
    ->anyStatus();
Entry::find()
    ->section('businesses')
    ->siteGroup(['siteGroupHandle1', 'siteGroupHandle2'])
    ->orderBy('title asc')
    ->limit(100)
    ->anyStatus();
@davidhellmann

This comment has been minimized.

Copy link

davidhellmann commented Jan 8, 2019

Damn, I need this too now :D

@kgrote

This comment has been minimized.

Copy link

kgrote commented Jan 12, 2019

I also need this!

@WeArePercipio

This comment has been minimized.

Copy link

WeArePercipio commented Jan 17, 2019

I needed this too so I've used the Twig array merge filter for the interim along with the excellent superSort plugin to sort the merged arrays back into chronological order.

Here's a simplified version:

{% set multiSiteEntries = [] %}

 {% set sites = craft.app.sites.getAllSites() %}
  {% for site in sites %}
  {% set multiSiteEntries = multiSiteEntries|merge(
    craft.entries().
    siteId(site.id)).
    section('blog').
    all())
  %}
 {% endfor %}

<ul>
{% for entry in multiSiteEntries|supersort('rsortAs', '{{ object.postDate|date("U") }}') %}
 <li>
  <a href="{{ entry.url }}" title="{{entry.title}}">
   {{ entry.title }} | {{ entry.postDate|date('jS F Y')}}
 </a>
 </li>

{% endfor %}
</ul>
@simonleadbetter

This comment has been minimized.

Copy link

simonleadbetter commented Jan 31, 2019

Yup. I’ve discovered that we need the ability to run an entries query across multiple Sites. Where is the preferred place to add feature requests these days?

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented Mar 11, 2019

Just pushed up the 3.2 branch, which implements this FR.

To update to it, change your craftcms/cms requirement in composer.json to:

"require": {
  "craftcms/cms": "^3.2.0-alpha.1",
  "...": "..."
}

Then run composer update.

As of d017022 you can pass multiple site handles to the site element query param (or multiple site IDs to the siteId param). You can also pass site('*') to query across all sites, or site(['not', 'siteHandle1', 'siteHandle2']) to exclude specific sites.

When you query across multiple sites, any elements that are enabled for multiple sites will be returned multiple times (once per site). This is great for cases when you want to create a language picker and get all of the localized versions of an entry at once. However there are cases where that wouldn’t be desired, so we’ve also added the unique param (5a28060), which can be used in conjunction with site, which will filter out duplicate elements from the results.

{% set entries = craft.entries()
    .section('news')
    .site('*')
    .unique()
    .all() %}

@brandonkelly brandonkelly added this to the 3.2 milestone Mar 11, 2019

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented Mar 14, 2019

We just tagged 3.2.0-alpha.1. If you’ve already updated a site to the 3.2 branch, please see the updated instructions above to update Craft to the tag, at which point you will be able to continue updating to new 3.2 releases like normal Craft updates.

@boxadesign

This comment has been minimized.

Copy link

boxadesign commented Mar 28, 2019

Hi, would it be possible to give a little more info on how to "create a language picker and get all of the localized versions of an entry at once". This is exactly what I need. I'm using element-api and have an endpoint and need to get the slug of all entries on other sites/locales with the same id to pipe into a language switcher (in a static site generator build). Below I'm attempting get the slug for the same entry on all sites but incorrectly. I'm attempting something like:

$allEntries = $entry->find()->site('*')->slug;

use craft\elements\Entry;
use craft\helpers\UrlHelper;
return [
  'endpoints' => [
        'posts.json' => function() {
            $langHandle = Craft::$app->request->getQueryParam('lang', 'en');
            return [
                'elementType' => Entry::class,
                'criteria' => ['section' => 'page', 'site' => $langHandle],
                'transformer' => function(Entry $entry) {
                    $parent = $entry->getParent();
                    $allEntries = $entry->find()->site('*')->slug;
                    return [
                        'id' => $entry->id,
                        'type' => $entry->type['handle'],
                        'title' => $entry->title,
                        'slug' => $entry->slug,
                        'locale' => $entry->locale,
                        'body' => $entry->body,
                        'level' => $entry->level,
                        'parent' => $parent ? [
                            'title' => $parent->title,
                            'url' => $parent->url,
                        ] : null,
                        'allEntries' => $allEntries
                    ];
                }
            ];
        }
    ]
];
@boxadesign

This comment has been minimized.

Copy link

boxadesign commented Mar 28, 2019

I managed to get the appropriate slug using the following (only selecting one 'site'):

$allEntries = Entry::find()->site('cy')->id($entry->id)->first();

and then:

'locale_slug' => $allEntries->slug

Although I updated to the release/tag stated above the '*' selector for all sites didn't work. It's not a problem for the work i'm currently doing as we only have one other language but will be adding others in the next phase of the project so would be helpful to know why it's not working. I updated composer etc

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented Mar 28, 2019

I'm using element-api and have an endpoint and need to get the slug of all entries on other sites/locales with the same id to pipe into a language switcher (in a static site generator build)

@boxadesign If I’m understanding you correctly, this is how you’d do it:

'slugs/<entryId:\d+>.json' => function(int $entryId) {
    $excludeSite = Craft::$app->request->getQueryParam('site');
    return [
        'elementType' => Entry::class,
        'criteria' => [
            'id' => $entryId,
            'site' => $excludeSite ? ['not', $excludeSite] : '*',
        ],
        'transformer' => function(Entry $entry) {
            return [
                'site' => $entry->site->handle,
                'slug' => $entry->slug,
            ];
        }
    ];
},

With that endpoint in place, you could go to /slugs/X.json to get all of the site handle/slug combinations returned, or you could go to /slugs/X.json?site=foo to get all the site handle/slug combinations excluding the site with a handle of foo. (In both cases, X represents the entry ID you want slugs for.)

@boxadesign

This comment has been minimized.

Copy link

boxadesign commented Mar 29, 2019

@brandonkelly Thanks for that it's very helpful. I definitely can't get the '*' to get all sites working though. This is after following your instructions of using the alpha release.

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented Mar 29, 2019

@boxadesign It’s working on my end. Can you email support@craftcms.com so we can help troubleshoot from there?

@davidhellmann

This comment has been minimized.

Copy link

davidhellmann commented Apr 3, 2019

@brandonkelly but it is not possible to have relations in the CP for that?
Our problem at the moment is we have a team channel with over 900 entries. and 30 multisites. We have to propagate this team channel over all the sites to select team members. Is there a way how we can handle that much smarter?

@brandonkelly

This comment has been minimized.

Copy link
Member

brandonkelly commented Apr 3, 2019

@davidhellmann Maybe you’re looking for #3584? (Also on the list for 3.2.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.