1

I have a field that determines which category my content belongs to, stored in a taxonomy vocabulary. The field is used in both the content type and the user profile. Users may select a category, but they can select only one and definitely not more. The content however can belong to more categories, in my case 2. So the field settings should be different, but that is impossible when using a single field. Whenever i change the maximum number of values in useraccounts to 1, the field in the nodetype changes to 1 also.

I use the same field to be able to make some views (starting from a user's perspective) to display content based on the users choice.

I see three possible solutions:

  1. Somehow use a field alias, enabling me to define the same field in 2 different ways. But i haven't found a mod for field aliases;
  2. Define two seperate fields with seperate settings. But i can't filter my output in a View based on the value of another field. Also, using a contextual filter won't work because there is no value to pass in the URL;
  3. Set the max value to 1 and add the same node twice, one for each category. Which is not the way to go, obviously.

Any clues to avoid option #3 ? I use D7 btw.

Thanx, Cas

0

Set the maximum number of values to unlimited.

Then using hook_form_alter change the categories select to only allow 1 value on the user profile form:

function YOUR_MODULE_form_alter(&$form, &$form_state, $form_id) {

    //drupal_set_message("Form ID is : " . $form_id);

    switch($form_id) {

        case 'user_profile_form':

            //dpm($form);
            $form['field_category'][LANGUAGE_NONE]['#multiple'] = false;
            break;

    }
}

If need be you could also add an additional validation handler here to add some custom server side validation to make sure that the user is not selecting more than 1 department.

  • Thanx Felix, this works fine for me. I had to change the widget from checkbox/radio to a select list because the #multiple identifier only works on select lists. But that is even better. I never made a custom module using a hook and had to dive into that, so you helped me in more than one way! – caskraker Mar 27 '14 at 13:38
  • Glad to hear it - now you can make custom modules anything is possible :) – Felix Eve Mar 27 '14 at 13:44
0

You don't specify exactly how the field is used on the User and Node Entities, but I'm assuming a User is able to pick a category of content to like/see/follow/associate with using a Term reference field, and Nodes are able to say they belong to two of these categories in the same way.

I would go with two different fields, because you really have two different use cases for a reference to one or more Terms in the same Vocabulary. I don't think it would make sense to filter users and nodes based on the same field in Views anyway, because it wouldn't work the way I think you want it to work.

Using the same Field on two different content types does not in any way actually link them together, or even imply they can be linked together. It just means those two content types needed the same settings for a Field, so why not create two instance of the same Field settings to make sure they'll always be the same.

In other words; "That's not a bug, it's a feature!"

When creating a View, one of the first things you do is to select the "base table", ie you're creating a Node (actually known as "Content" in Views) or User type View. Assume you want to display "every" item of this type (SQL's SELECT * FROM foo). If you create a Node/Content View without filters, you'll get all Nodes. You may link in User data (through the author or another field) through Relationships (SQL JOIN bar ON foo.x=bar.y), but you'll never see all users listed just once or a single row with just a User, since their data is just joined to the Nodes. The same is true for Nodes if you start with a User based View.

Filtering on the same field for more than one content type is useful when your content types are similar or closely structurally related somehow, and are both of the same base type (bundles of say Nodes). This way you can truly list all of these items just by making a Node View and filtering out other bundles, without any joins, so they're both first class items. Then you can get a subset of both types of content by adding a single filter on the [Term reference] field.

However, if the same field is used on Nodes and Users, you'd have to tell Views which instance of that field to filter on by, selecting the Relation to use (if any), ie which table (node or user) to use. (View generates one alias for each table a field is used on automatically, but it can still only compare a filtering value to one of them with one filter, and aliases still use Relationships/JOINs.) This means you either get a subset based on which Nodes are in a category, or which Nodes were authored by Users that have selected that category.

This is because filters currently (until Views 7.x-3.8) only filter based on a fixed value (using one of several operators), and not the value of another field.

Just to cover a corner case; if you also add another filter, filtering on the same Category value, but using "the other" table as the Relationship (User in a Node View or vice versa) you'll end up only with Nodes in the same category as its author has selected, or only Users which have created Nodes in the category they like. This type of very narrow subset of Users or Nodes would also be generated if you picked any other two fields (one from each of User and Node) to filter on, since the "Content" Field being instances of the same Field settings does not really matter for the result set you'll get back.

Since you want different settings for Term references, create two separate Fields. One for Nodes, allowing two Terms, let's call it "Categories". One for Users allowing one Term, let's call it just "Category". This will actually make it slightly easier to navigate in the Views UI as you can clearly see which one of the Fields belongs to Nodes or Users later on.

Now, if you're looking to fetch Nodes based on which Category the current User has picked we'll have to figure out exactly what that relationship looks like. A list of Nodes is not directly relatable to Users, unless the user happens to be the author or there are explicit User/Node reference fields linking them together, so let's break this down in steps.

Start with a Content View, add at least the Title field and the "Content: Categories" field just so we know shat we're getting back from the query. Sort by the Node title or whatever makes sense in your case.

Nodes hold the term ids in our Categories field, but we need the actual Term data, that's one Relationship in the right direction. Add a "Content: Categories" Relationship. Make it Required since we don't want Nodes without Categories set shown. By now your result set will include all Nodes with two Categories set twice, because of the JOIN this created. That's fine.

The Terms are also being referenced by a field on Users, and adding the previous Relationship between Nodes and Terms now allows us to go one step further. Add the "Taxonomy term: User using Category" Relationship and make it required as well. By now the result set will have multiplied the number of times a Node is shown by how many Categories it has, and again by the number of users which have set one of those Terms in their own Category Field. That's also fine. You can now add a "User: Name" field to see who has chosen the same category used by the Node (note that it's using the Relationship chain).

Now we have established a link from Nodes to Users. Time to limit things to the User we're interested in: the one currently logged in. By now you'll be able to filter the result set based on any User data available through the Relationship chain, including the logged in status. So add a "Current user" filter and set it to "Logged in".

By now, your query is pretty much unreadable, but it works! ;)

In this case we're lucky User can only select one Category, since that prevents multiplying the number of times a Node is shown by the number of matches between the Category and Categories fields. But if you do need User to be able to select multiple categories later, make sure you tell Views to only return unique/distinct matches.

If some of my assumptions are wrong, please comment and I'll update the answer accordingly.

  • Thank you for this elaborate clearing! Because my View already worked when the user selects only one category i was helped with the above tweak through hook_form_alter but your text helped me understand Views/Queries a little better. I will certainly return to it when i need to. – caskraker Mar 27 '14 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.