 All right, so I think we can go ahead and get started. All right, so you should be in the presentation view section if you're in the wrong room. Feel free to exit. So what do we do when we need to store some data and provide a fancy display for our end users? Say we have a company with information about employees, and that company wants a directory display on their website. Well, maybe it's not for a company at all, but instead a supervillain named FiloniusGrew. So it seems like a fitting client as most of mine act like supervillains from time to time. So if you're familiar with Grew, you'll know the infamous minions that helped him carry out his evil bidding. And Grew has assigned his minions tasks. And through these tasks, they inherit job titles. And as a web developer, it's our job to create a presentation of this data. So today, we'll demo a solution for this, and I'll share a modular views concept I call Viewception. So good morning. My name is Brandon Ratzloff. You can communicate with me at Brandon Ratzloff on Twitter. I am a lone Drupal developer for conference management and event planning company. I have nearly seven years of Drupal site building experience. I started working on a content management system called Joomla. Might be familiar. At one point, I was looking for a solution to sell video subscriptions. A friend of mine pointed me to Drupal 6. I found an Uberkart node access module. And from the vague module description, seemed like the adequate solution. So I found Drupal had a much higher learning curve. But thanks to the amazing Drupal community, I got to where I am today. For example, I can give myself a fancy title like Site Solutions Architect. So as a Drupalist, I've come to the conclusion that I'm supposed to know it all. And honestly, when dealing with clients, I do have to know it all. So win site building, try to know it all, and know it all the Drupal way. So the goals for this session are going to be think more deeply about your content structure. Content is stored in the database. So think like a database administrator. And I'll help you expand your views toolbox. We'll review a few modules, give us more flexibility and functionality. And we'll help take control of the duplicate results in views. So why views returns duplicate results and propose a solution. And I'll share a modular views concept. And we'll explain how to break our views into pieces and then recombine them. So again this morning, I will review a little about relational databases and data modeling, why relationships are necessary and how they complicate data removal. We'll look at a different approach to displaying content through modularity in views. I'll perform a live demo on combining multiple views to gain ultimate control. So we're gonna stay 100% in the user interface today, so plan accordingly. So let's put a few things into perspective and talk a little bit about this data modeling. So in a database, tables are used to organize different types of content. The complexity of the content sometimes requires us to organize the data into parts. And these parts become separate tables in the database. If different types of data relate to one another, you can connect them. And these are called relationships. A table's given relationship to another is referred to as its cardinality. These relationships might be a one-to-one, a one-to-many, or even a many-to-many. And a one-to-run relationship might be employee to their name or a minion to their photo. And a one-to-many relationship could be a department to their various employees or a minion to their assigned tasks. So has anyone ever seen the Drupal's entity relationship diagram? Hands? Yeah? Some? This is a picture of Drupal 7's database tables. So every box here is referred to as an entity table, and the lines represent the relationships of cardinality. I might note this is without any additional content types or fields added. It's vanilla Drupal. So as you can see, a data model can get very complicated. So why review these modeling basics? Because creating content types and adding content is a form of data modeling. And views looks directly into your database to create its displays. So when creating content types, the Drupal user interface reacts with the database and does all the grunt work. Drupal works very well as a data modeling tool. The bottom line is to know every time you create a new content type or a field, you're actually building tables in your database with these relationships. So here's just an example of a data model, maybe with Drupal terminology. And then we can see how that data model might be translated into human readable terms. So how do we get the data out of this database we've been designing? So we use a language called SQL, structured query language. It allows us to interact with the database and we use CRUD operations, which are create, read, update, delete, right on our database. So we can write select statements to select and retrieve our data. If we have multiple tables relating to one other, we can use join statements to bring them together. It can take extremely complicated queries to get the data we need. So I found this image lurking on the internet. I was not aware until this time you can write a six page query, apparently. So yeah, if this is your idea fun, we probably won't have a lot in common. But enough of this SQL data modeling junk, let's get down to business. So what is views? Views is a query building and inspection tool. So it allows you to create a page or block or attachments displays right out of the box. It uses render plugins to output various different types of markup. So a large majority of your database is available through views as long as it uses the entity's system. From the module page, it does say you need views if and it lists some common reasons. I propose we say anything worth doing requires views. Views however powerful still requires you to know what you're building. And so a quick overview of what views does do for us. When adding a new view, we're starting our select statement in the query. So through the add new view screen, we start by choosing our base table. It will allow us to set up some filters like the type of content. These are actually where clauses in our query. And this page will also give us a sort order, which is order by clause. And then finally, the number of results, perhaps, which is the limit clause. So with these options selected, we've actually built a full query and views can use it to render our content. Some of you may not be aware, but you can actually inspect your query directly in the preview section. I don't think this is set up by default. For this, you can change your views settings and that's available at admin slash structure slash views slash settings. And I do advise you take a look at this page. There are many tools that can help your mastery of views. So one way to help you understand the views interface is to split it into parts. So one for formatting a display and the other for how to select and filter your query. As shown in yellow, we can see our selected fields, relationships and contextual filters. And then blue shows us the type of page block or attachment, so the type of display. And also the markup formatter and other page settings. So now we're pretty much ready to build our view. We know all these things. So looking back in our slides, here's a refresher on the data model we've designed and a quick diagram showing the relationship between our minions, their jobs and tasks. Sorry, there's a little typo there. You may expect this model to complicate your views results. And so a common problem when querying data models like this are duplicate results. So if we try to select every minion and his tasks, we've actually joined our one to one fields, the photo and name with our one to many, like the tasks and job titles, together. So when we print our results row by row, we'll get a multiplying factor on our fields, generally one set of minion fields for every term. So some solutions might be aggregation. It tries to combine all the common fields and it's kind of applied to all parts of the view. I think it seems a little clunky and it doesn't give the control I'm after. Also there's a setting in the query settings called distinct. And by definition it's meant to display only different or distinct values from a table. It'll only work in specific use cases. So a module I'm not gonna demo today but deserves honorable mention is views distinct. And views distinct is intended to assist in the removal of duplicates on individual fields. It provides aggregation or filtering options per field in your view. So it's worth taking a look at. So if not for these more common approaches than what? Viewception obviously, right? So viewception is a modular views building concept that provides full control over each level of your view. It leverages the help of views field view module to embed views as actual fields. So our goal with this concept is to build each view out to provide just the necessary results and then recombine them. So in a demo I'm about to do, I will go ahead and build three different views. It's gonna be one for the minions themselves and one for the job titles and one for our tasks. So then we'll combine them into one display like it's illustrated here. So that's all I have for the slides and I'm gonna try to see if I can't change my display here and get the correct thing showing on the screen for you guys. All right, so we all should see the minion directory website here. Is that what we're seeing? Got a look for myself. Okay, so I've pre-made a few things in this website for us to move us along. So the first thing I wanted to talk about is whenever you're creating anything, of course, you wanna prepare your content. So you wanna gather your content types and if you have taxonomies, you wanna get those in order. Be a forward thinker, I guess, when designing these type of things. So the first part of this I've actually set up is a taxonomy with jobs and this uses a hierarchical structure. So this is something you may or may not normally run into but I wanted to show this because it's kind of an advanced way, I guess, to deal with these type of hierarchies. So in this case, I've actually done something where you've got your job titles on top and then perhaps the tasks underneath so it's a parent-child relationship in that way over here. So then I've gone ahead and created the content type minion. I've just changed the title field here, the label to name so no big changes there. Added a photo field and perhaps what a minion loves just to add a little bit of flair to our minions themselves and then I've gone ahead and used a term reference field which is pretty common to actually build that relationship between my minions and that vocabulary of the different jobs. And so just to kind of preview what I'm gonna put together for you today, we should end up with a display with something like this. So there's actually three views, different views working here and they're all embedded together. So I know demos are sometimes looked down upon but I'm going to go through this and I think we're gonna be successful so no worries. And just in case I've got them all pre-made so we can just look at them if we want. All right, so the first view I wanna make is going to be for my minions themselves. Make sure that's what I actually wanna do. Look at my little demo outline here. Okay, so I'll just give this a quick name and for this we're actually jumping right into the content tables and we're gonna go ahead and use a filter for minion and I don't care about how it's sorted and I'm not actually creating a page because this particular view is gonna be embedded so I'm just gonna create a block. So I continue and edit that. First thing I wanna make sure of is that all of my items do display. I don't need any limiters on this. I don't like that that's actually a default in views but I do understand. So I'll change the format settings. I like to use a module that enables semantic views that just gives you a better markup results. And then we're actually gonna choose to use show actual fields here so we're not using a view modes or anything like that. So in the fields I really, I just want the title. I'm gonna want the photo and then what a minion loves so we'll just add those really quick. Manipulate a few of the settings. We don't need any of the labels, the formatter for the loves is just fine. It's just a plain text field. Remove the label for the image. Got some pre-designed image style here. I think that's actually default. I'm gonna copy in some classes that I have to make everything look a little bit better. All right so once we do have those standard fields, those are like I said the one to one type of fields. I'm gonna rearrange these real quick. I actually want the photo on top. I'm gonna add that relationship to its jobs or to each minion's tasks here. So I can just go through the content, add the actual, the content jobs field there so I'll get that term reference connection. And what I want to build here is I only want the results from an individual task. So I'm going all the way down the tree and I'm gonna decide that if he is a dishwasher then I only want to receive those minions as results. So I'm gonna add a contextual filter here based on that relationship that I just built opens up the taxonomy terms for me and simply use the term ID because I'm not gonna need to know this. Later on it's gonna be automatically embedded so I will add that and hide the view if nothing is provided. And then we get no query down here. I do know, I believe it's eight. Eight should give us a set of the minions that actually are the dishwasher so we have three results there. There's no titling of the terms or anything like that. That's exactly what I want. So I can go ahead and save this particular view and I'm going to add now my tasks. And for this we're gonna start directly in the taxonomy table and go ahead and filter out based on our jobs. And again this is just going to be a block because it will as well be embedded. So we continue and edit that. Gonna remove or go ahead and display all those as well. And here I'll just use the semantic views formatter again and the key is of course we want to get the fields printed in here. So at this point we are looking at receiving all of our sub, we want to try to get all of our sub tasks and we can see that we've really just queried all of the tasks on an equal level. So Mad Scientist no longer has its hierarchy. So here's kind of an interesting trick and maybe you can add this to your views arsenal. So how we want to go ahead and parse out the tasks instead of getting the parents, we can add a relationship and this is kind of an introduction of a module. I believe it's called views arg parent term. So write that down views arg parent term. And so that gives you a new taxonomy term, parent term relationship that I can add to this particular view. Use the identifier parent. And so nothing has changed at this point. We're just identifying the parent and what I want to do with that relationship is go ahead and add a filter and I can use the ID again and I'm going to use that parent relationship and here I'm going to make sure that it is not empty. So therefore we know that there is a term above it and this actually identifies that it is a sub term so it's a child in this case. So now we know we're only getting our tasks in our hierarchy that we've created. So I scroll down here, we see that I've now removed the top job titles as I've referred to them. So this view is done for the moment. Well at our final view and this actually going to be a page view so this is going to be the jobs themselves and this again is in the taxonomy terms table because it is for the job titles we're looking for. Sorting doesn't matter but we're actually going to create a page this time. Like I said, we'll just use the path demo. Minion jobs helps to practice this before so it's auto filled in. Here we'll use that semantic views and fields once again. I want all everything to display there so I don't need pager. Continue and edit that. I apologize, I want to go back here real quick. I did want to actually test this so if I put in mad scientist for example on the tasks view that I just created and update that preview, I should get, oh, okay so this is why demos get a little hairy. The one last thing I did want to add to my tasks view after the highlight of only identifying the sub tasks is I wanted to add a contextual filter and then only get the chosen tasks that I actually wanted here so I was meaning to add another contextual filter on this view and I'm gonna use that parent relationship once again there so then if I do select five for example being a mad scientist I do only get gadget tester and toxic waste on dumper because those are the tasks of the job title so I apologize for having to go back there. Okay so back on the job titles we're just trying to get a full list of our job titles here so just like on the previous view we're gonna wanna add that parent term relationship once again with the parent identifier get a filter in here to remove all of the child terms and so in this case we'll use that parent relationship but we're actually gonna make sure that it's empty because we don't want anything above it so when we apply that to the display we will end up with just our three job titles as we've defined them and so that's actually where I'm looking kind of phase one so I've built all three of the views now I actually wanna take each individual one and kind of plug them into the other and like I mentioned the views field view will allow us to do that so I will start back on my task view and remember just doing some checks all right so I'm actually looking to add underneath gadget tester and toxic waste dumper the view of the minions parsed out using their taxonomy or contextual filter to give me just the results I want so what I'm gonna use here is I'm actually gonna add a view and after enabling the views field view module I get this global view and I can add this in as a field and it gives me a couple extra options here and the key items you wanna look at is actually what view we are inserting into this field and so in this particular case we're on the tasks view so I want only the minions brought in here so I'm gonna choose my demo minion directory and I can choose the block or master whatever display you've created and the key here is we can actually send architectural filters or send a token or send any identifier we want to the other view through this so when I apply the display I actually don't have any changes just yet because I didn't have a field to add to push over to my minions view for that contextual filter and remember on the minions view our contextual field was filter was actually the term ID so in our tasks view I need to add that specific term ID to our field set here so I'm gonna go ahead and add that I don't need this displayed at all it's just to use in the views field and of course when creating your views in this way we need to make sure if we're going to get the tokens and such available in the replacement patterns we need to have our fields above the other field so I'll put my term ID above my global view that'll actually give me a replacement pattern for that term ID which I can plug in to that view field and once I've done that I've actually passed the taxonomy term for each individual row of a task to the minions view and so when those are combined together in this way I should receive gadget testers or Dave and Jerry and the toxic waste dumper would be Tim and George so at this point it's just up to you to work on how you'd actually like to display that but you have control over each individual level that way so I'm gonna save that one and the final thing I wanna do is go ahead and basically do the same to my job titles view so knowing that I have to add the term ID here I'm gonna go ahead and do that and then add my global view field view and one more time and on this one I'm looking to select the tasks view that I've created and I'm gonna use the term ID once again in the contextual filter because that's what I'm actually passing down to that other tasks view that I created so here we should be able to see exclude that display so we should be able to see now the gardener and his tasks and then the actual minions then are attached to the tasks which are then that group is then attached to the job titles so I think it's a pretty cool concept let's go back and take a look at what I actually you can actually turn this into so the mad scientist again was the job title in this case and then a sub item the terms would be gadget tester and then I've attached the different minions directly to gadget tester and attached gadget tester to the mad scientist so I'll take a quick look here at the view I just created and all right so it doesn't look like the other view that I created and again as I mentioned it's all up to you in styling so this is just a lesson in design I suppose I do have these individual items kind of blocked out and what you're able to do once you have this configuration is go ahead and define exactly how each individual view that you've created does look so if you need a view within a view to look different than maybe the top view or something like that you have that full control so that's a really great way to do your views that to gain that extra control anybody want to actually see just what I applied to actually get that visual styling is that important to anyone? Maybe, no? Okay real quick then so I've also used in the jobs there's another module you can use responsive grid views responsive grid I believe and I'm using a particular grid system here so I'm able to go ahead and change how many columns I want and so on and so forth and I think it's a bootstrap theme so I'm able to apply different classes just directly to each one of the individual views so I get the results that I'm looking for and I'll go to my pre-made view here just so we can see that so when I choose the responsive grid and go to my settings I'm using two columns for the different tasks and some different column classes to help outline that in the row and so on and so forth so it just kind of gives you a quick example of how much control you might gain over this actual display so that's the demo I think it worked out kind of, yeah? So really I'm ready to take any questions if you guys have any yeah so the question is about performance and I haven't spent a lot of time analyzing that specifically I'm running in kind of a varnished, cached environment and so with that I've had no real issues I will say there absolutely is and you need to analyze that this was pulling out five pieces of content with various fields so we're looking at a very small example if you have thousands and thousands of nodes it's definitely going to be a bigger hit than trying to do everything in an individual query and I'll say caching results are a little bit mixed because it's a query within a query it does if it tries to cache one you usually won't get the actual results you're looking for so usually you can't use full caching on in your individual views because of that yeah so views field view is the actual name of the module I'm using to it gives you that global global view field that you can plug in and you can actually use that I believe directly in the header and footer as well so it's another way right so I'll give you a quick example I have somewhere in the range of four or five hundred different abstracts on this particular website and I've actually built so all abstracts belong to multiple categories so for this example I want to be able to filter out only one category and not see the other groupings of the category so I've actually done a view in bed here so if I was to select one category I only see one title even though a different category might belong to category three or sorry a different abstract might belong to category three for example and so that yeah that's how I use that and so to directly answer the question I've used four or five hundred nodes in a query and this loads pretty quickly especially I'm logged in so it's just up to you to do kind of the testing there right so it's kind of a lesson in naming conventions I guess yeah and I struggle with that same thing so for this demo I started each view with the name demo you can actually use over two of you here so in our demo jobs if you wanted to you can create multiple displays and then once your view is saved then those become accessible to the to the view field so that's one way to organize it I think it just makes it more confusing in a demo case but usually that's something like I'll do and then I'll also combine it with view modes itself which is actually what I did with the abstracts instead of making a set of fields as a view I just use a view mode and then just call on those and then embed that set of view I guess view mode nodes into another view does that answer your question? yeah okay anything else? okay I don't I don't know of any documentation I used a lot of contextual filters I guess when they were arguments right in Drupal 6 so I really just try to look at them as they're another way to filter a dynamic filter right so right yeah you could give a whole session on that yeah I don't think I have either myself and you know because then you can get into you know dynamically writing your dynamic filters so you could do uh write a custom PHP in there and that type of thing which you know so you have to convert your handler and this and that so it gets kind of it gets really tricky but sorry I don't have any documentation for that right right so so I guess it's a good thing I gave this particular example if I used group by and did this in a single singular view uh I'm querying in abstracts like I said with their um categories as a field let's say and if I used group by it's going to try to either it's gonna if one abstract belongs to two categories it it has both of those available to you so the only way to get only one category to show here would be that either um well to do it this way or you could filter or aggregate that group by result and so that's really where the group by I guess for me I run into a lot of problems uh I don't I don't know if I explain that well at all I guess did that make sense I think so so yeah I mean group by is like what it's aggregating uh on one field and then taking out it out of the display and and uh so if you have if your different nodes have multiple uses of that field and it's name different it's gonna have to try to combine those or display both of them so if it's if one of my abstracts here belong to category 11 and 10 and I do a group by display I'm gonna get category 11 and 10 grouped on this display but that's not what I want I only want the results of of 11 here so anything else yeah it kind of comes down to how you I guess how you want to design that I wanted to show that example so you could see that hierarchy is manageable here but I think there's a vast number of other modules like sorry I'm not really familiar with them but for managing hierarchy in in taxonomy itself like hierarchical views or I think is one or something like that I definitely think you could use this method I wouldn't go I wouldn't go too far with it but again I use it for its strengths of being able to have control over each one of those those levels so even if I only have two levels of hierarchy I have to make three views that way four would be it could definitely get out of control so I'd explore and see if it's manageable otherwise try to take a different approach so it I'm not a hundred percent here but it could be when you actually run when you're doing a sort on a different field that's pulling it into the query so it might give you be giving you those duplicate results just because of like this same this same problem so it's I guess the view seeing that field and and yeah it does kind of blow up on that level and I guess this doesn't worry about your duplicates it's okay because you're filtering amount anyway through contextual filters so it gives you the exact I guess set of results you're looking for and so when using sorting it's not it's not a concern of like that additional I don't feel being there so I think that it would it would help so I don't know if this correctly answers your question or not but in sorting there is a views natural sort module that that might assist you in that I know I know one of the problems you're gonna have is is like is just perhaps your sorting sorting will be incorrect because of of that particular item but I I can't think of the top of my head exactly you're looking to to sort the taxonomy and then the items within right or yeah well maybe maybe come chat with me after and we can think things up and up yeah sure right okay right yeah I can't I can't elaborate a lot but I know said there's like a there's like a query hook with views so you can just override your actual query and then send it back to your views so it kind of overwrites it like the same way maybe a template file or something like that would so maybe look in into just writing that hook to call on your view I guess write your own query and then maybe you can get the data back that I'm not 100% sure how that works but it's off top of my head an idea anything else that last part would that be adding a query and a module you would write yeah yeah yeah okay right right yeah then you what you'd have to start writing your own handlers and such all right well thank you so much guys enjoy the rest of the conference