moving database schema over to drupal - drupal

I'm creating a web application and I just want to know how to think about Drupal's db coming from an MVC background.
I have tables to represent people's data such as SSN, First Name, Last Name, Zip Code, Address, Language, Location. Now on the front end I want to create a form to populate this information for a bunch of subjects (people). I have my database normalized so the Zip Code has its own table (with a foreign key link to the person table). The "person" table has stuff such as First Name, Last Name, Address etc... and the "language" table will have the different language abbreviations (again with a foreign key back to the person table).
I would like to know how to move something like this to drupal's schema. I know I could create my own tables and link them back to the "node" table and then I guess build my forms to accept user input...but is this the suggested way to do it? I was looking at webform, but it seems this should be used for simpler forms where the database isn't normalized and everything is just stored in one large table. I'm not sure, but I would definitely love to hear what you guys think...and if you could point me to some resources that'd be great.

Drupal is flexible enough that you can create whatever tables you want and then write code to link them back to the node table. However doing this will mean that you end up with a lot of code which is very specific to your schema, and is not very interoperable with other Drupal modules.
You will find that you get on better with Drupal if you mostly do things the Drupal way. And only go for a very customized solution where you are doing something which isn't covered by standard Drupal modules.
For example you may find that the profile module fits your needs as far as standard information about people goes. The location module (specifically user location) will cover users addresses. By using these modules you are more likely to find other modules which work with them in future and overall you will find you have less code to write.
One thing you may find useful is the migrate module for getting your existing data into Drupal.

It sounds like you're just storing information and the subjects (people) won't be users of the Drupal site.
Leveraging the node and CCK modules to make this happen would remove most of the development work. For example, each of your tables (e.g. Person, Zip Code, Language) could be represented by a content type with a number of fields. The foreign keys would be represented by node reference fields. So the Person content type may have one or more node references to nodes of type, Language.
The migrate module seems well used (626th most popular of 4000+ modules used in at least 10 distinct Drupal sites), but it may be easier to whip up your own migration script, but I'm not familiar with either your situation, your familiarity with Drupal's API, or the migrate module.
Node reference fields display as links to the referenced nodes by default, but can be themed to load and display the referenced node instead (e.g. displaying Language information in a Person node). There's a handy screencast that illustrates how to go about theming node reference fields to load and selectively display the referenced nodes' contents.

Coming from an MVC background you may not like how Drupal stores data in the DB.
Profile module was mentioned, but I find I get more flexibility with Content Profile and CCK combined.
I've written some migration scripts before from Coldfusion to Drupal, and it's not too involved.

Related

Drupal best practice for complex relationships

I'm designing a Drupal 7 website where nodes/entites have complex relationships (1-many, many-to-many). For example:
Student (registered user) can belong to one ore more classes
Student can take one or more exams each semester
Teacher will take a note about each student in his class after each semester
My main concern is about:
Performance: queries should be fast and simple when rendering pages
Relationship: need to have two way relationship ( => can list related content based on content or vise versa)
Views Integration: should be fieldable and easy to list related content in Views
==> I come up with 2 solutions:
Method 1: the Drupal way
I know that there are some modules like EntityReference, Field Collection,... but don't know how to use, mix them the right way. Let's say how to create content type for a class, it's fields that link to user table and then easy to show the list of students on a given class?
===> The question is: What is the best practice for my case and what modules I should use and mixing together to solve this problem. What content type, it's field, and relationship I should create?
Method 2: could be not the Drupal way
Normally, I will design some tables in 3rd normal form (3NF) for those entities and their relationship: student, teacher, class, exam...I mean that this approach could be not the Drupal way as normal with field_xxx magical tables for each field of an custom content type, right? Hereunder are example of them:
Student table ( uid, name, full_name, other meta data columns) , of course the uid is foreign key point to Drupal user table
Class table (id, name, code_name,...)
Student_Class junction table (student_id, class_id, semester_id)
etc,.....
===> The question is: If I do it this way, is there any module which support to auto generated create CRUD forms, or API to create form to manipulate those tables, easy to allow field-able with Views module.
Please correct me for any misunderstanding and your ideas are welcome.
Thanks
The Drupal way with Entity Reference, Views, Field Collection (I would add Inline Entity Form, Views Bulk Operations, Views Megarow) is, in my opinion, the good one : you will be able to create back-office (and front end) screens very (I mean very) quickly using Views, related content (using Entity Reference) can be fetched both way, Inline Entity Form allows you to set up creation forms containing the related entity creation form (so create an entity and its related entity at the same time). Drupal Commerce is a good example of what you can do with these modules (see this entity relationship model). Rules can help to set up your business logic. So points 1 & 2 are (can be), in my humble opinion, satisfied with the Drupal way.
BUT...
This flexibility comes at the cost of complex requests, and eventually bad performance. You'll find all over the web posts about how Drupal is slow, and when you start playing around with a complex setup, it can be a serious problem. But with a good server configuration (cache, proxy...) and no PHP in Views :), it can be done (I run several Drupal Commerce sites, with a good server and a good sysadmin it's ok).
And you'll have to dive into Drupal logic, Views logic, Rules logic, which can be frustrating at some points : something you would code in a few PHP lines will take you a lot of clicks in Drupal interface. Of course, for tricky things, you can always build a small custom module doing just what you need.
About the second solution, I have no experience to share on Drupal and custom data model, but I guess you should consider applications frameworks (Symfony, Zend, CakePHP...) if you want to be free for the DB design.
Good luck

How to create the best Drupal 7 structure as a site builder - via Entity type or Content type?

Just started using Drupal and tried to understand the core concepts. I have a developer background but I would like to use Drupal as a site builder and not digging into the code.
I'm trying to build a website which lists various vendors. One could be a Restaurant, another can be Photographer and other possible services (I have like 15 different ones).
They all have some things in common like Title, a Location (used Taxonomy/Vocabulary for that), description, image gallery, address, website, office hours and so on.
But they also have some custom fields. Restaurants can have fields like Facility options:Parking, Smoking area, etc or Capacity; Photographers can have others.
So there are lots of fields which are common for each vendor and some are are unique per each vendor.
What's the best way to implement this kind of structure as a Site builder?
I tried using Entities via ECK (Entity Construction Kit) and defining Entity types (as Vendor) and Bundles (as specific Vendors) but then I'm really limited in defining the common fields on Entity type level since Properties does not seem to be flexible in this regard, meaning that I cannot define them as normal fields and can't associate to them various widgets but only as a text input. Not sure if this a limitation of ECK or of Drupal 7 itself?
On the other hand I see the option of creating normal Content types for each kind of vendor which seems like alot of repetitive work, not sure if this is the right way (that's my only option at the moment)?
Maybe I should start learning more of Drupal and do some coding to create specific entity types? - but this means being more than a site builder. Since it will be a big project will this save me of some trouble later on or you see that I can accomplish the task easily without this extra effort?
Also by coding I'm not sure if there are easy ways of defining fields/widgets for Entity type Properties.
I would later on want to use faceting as well for filtering which will be based both on the fields which are common and unique for each vendor type, not sure if this is an important factor when creating the structure.
Any feedback is appreciated!

How to do database queries with Drupal 7 without coding?

My professor recently gave my class an assignment and I need help finding the tools to do so.
We have a database of tables (Customer, Payment, Order, etc.) and I need to use Drupal 7 to allow users to see customer's info, view customer data (i.e. payment history), or edit customer information. This would involve select statements, aggregate clauses, joins, etc. It would also involve forms to input customer name/information.
Here is the catch: I am not allowed to write any code. That means no API, no SQL queries, and no PHP. I am only allowed to use ready-built modules.
So my questions is: What module(s) should I use, and how do I use them?
I know the view is a good place to start, but the default options of view are for content. I have tables on a database, not content. Also from what I understand, custom queries of view require coding.
I believe this is what you are looking for:
http://drupal.org/project/data
If it integrates with the Views module properly, then you won't be required to do any hand-coding to make a View which queries your tables.
(Disclaimer: I haven't actually used it)

Field data in one table, not many. for drupal7

I am working with the commerce module to create an online store. I am modifying the products .install file to create a content type (as I have been told this is required) and as part of that content type, I need to create lots of fields. The list will be around 50-60 different pieces of information.
Ideally I would like to store these in a single table with the productID at the beginning and all the other information along, but this doesn't seem to be the case; all the fields are stored in different tables.
I noticed that the "Address" module that is also used with commerce creates a field-type that has about 15 different values all stored in the same box. How is this possible? I noticed that if I set the cardinality up to 5 for example, it creates different rows. I just want a table with the following:
ID - value1 - value2 - value3 etc etc.
I also don't need any modules/extensions as this all needs to be written in the files. I also don't think that changing to the mongoDB ( I think ) is an option, so what are my options in this situation?
That's not how the Drupal field system works I'm afraid, one field == one table (well actually 2 tables if you include the revision table for each field).
The Address module uses hook_field_schema() to define several columns for that particular field (have a look in address.install and you'll see what I mean).
So if you want to put everything in one table you'll simply have to define your own field type (see the examples module, specifically field_example for help with that).
Bear in mind though that the number of columns you define in hook_field_schema() will be static once the module is installed, and the only way you're going to be able to increase/decrease it is with an _update hook for your custom module.
Also, if you're hacking at files that are included in the Commerce module...stop!: Commerce is still very much in it's infancy and you will likely have to update it soon...once you've done that your code changes will be gone and there's a good chance your site will be in an inconsistent state.
The whole point to Drupal is that everything is hooked/farmed out so that it can be altered by other parts of the system. There's nothing you can change in product.install that can't be done by implementing a Drupal hook in another module.
If you're unsure, post another question detailing what you're trying to accomplish by directly editing a contrib module file and one of the Drupal gurus on SO will point you in the right direction :-)
EDIT
Just to say I've been working with Ubercart in Drupal 7 for quite some time now and find it a very, very good solution (a lot of Commerce contributed modules are still in dev/alpha/beta; this is less so for Ubercart contributed modules). It might be worth a look.
Some more info
I think you've basically got two options here but either way you'll need to create a custom module (excellent set of instructions here).
Option 1: Create a custom field
If you're a Drupal coding beginner I'd suggest this is probably the easiest way to accomplish what you want, but it's still not totally straight forward. Grab the field_example module from the Drupal Examples module link above and have a look in the .install file, specifically the field_example_field_schema() function. That defines the columns that will be in the table for that field. Then have a look in field_example.module...pretty much every function that's commented with Implements hook_x is one that you're going to want to copy into your module and tweak for your own needs.
I think this will be easier because Drupal will handle the table/form field creation for you
so you don't have to mess with the database, schema or form APIs.
Option 2: Create a custom module
This option involves implementing your own table (like you suggest in your comment) where the primary key would be the entity ID of the product and would also contain all of your custom columns. (See the Schema API documentation for help with this).
Then you'd implement hook_form_alter() to add the form fields necessary for a user to input the data, and then implement hook_node_insert() and hook_node_update() to persist this data to your database table. It's quite hard to go into any more detail without actually writing code and it's quite a bit of code!
Hope that helps, sorry I can't be any more specific but it's not easy without knowing all the ins and outs of the situation

Best way to save extra data for user in Drupal 6

I am developing a site that is saving non visible user data upon login (e.g. external ID on another site). We are going to create/save this data as soon as the account is created.
I could see us saving data using
the content profile module (already in use on our side)
the profile module
the data column in the user table
creating our own table
I feel like #1 is probably the most logical place, however creating a node within a module does not seem to be a trivial thing.
#3 feels like a typical way to solve this, but just having a bunch of serialized data in a catchall field does not feel like the best design.
Any suggestions?
IMO, each option has its pro's and con's, and you should be the one to make the final call, given that you are the only one to know what your project is about, what are the critical points of the project, what is the expected typical user pattern, what are the resources available, etc...
If I was totally free to chose, my personal favourites would be option #4, #1 and #5 (wait! #5? Yes: see below!). My guiding principles in making the choice would be:
Keep it clean
Keep it simple
Make it extensible
#1 - The content profile module
This would be a clean solution in that you would make easier for developer to maintain your code, as all the alteration to the user would pass through the same channel, and it would be easier to track down problems or add new functionality.
I do not find it particularly simple as it requires you to interact with the custom API of that module.
As for extensibility that depends from how well the content profile module API is designed. The temptation could be to simply use the tables done by said module for your purpose, bypassing the API's but that exposes you to the possibility that on a critical security update one day in which you are in a hurry the entire system will break down because the schema has changed...
#4 - Creating your own table
This would be a clean solution because you could design your table (and your module to do exactly what you need to), and you could create your own API to be used by other modules. On the other hand you would introduce yet another piece of code altering the registration process, and this might make it more difficult for devs to track problems and expand the system in a consistent way.
This would be very simple to implement code-wise. Also the DB design would benefit though: another thing to consider is that the tables would be very easy to inspect and query. Creating a new handler for views is dead easy in most of the cases: 4 out of 5 you simply use one of the prototype objects shipping with views.
This would be extremely easy to extend, of course. Once you created the module for one field, you could manage as many as you want by mostly copy/pasting the code for one field to another (or to inherit from the same ancestor if you go OOP).
I understand you are already knowledgeable about drupal, but if you need a pointer on how to do that, I gave some direction in this other answer.
#5 - Creating your own table and porting already existing fields there
That would essentailly be #4 minus the drawback of scattering functionality across various modules... Of course if you are already managing 200 fields the other way this is not a viable option, but if you are early into your design, you could consider this.
In my experience nearly every project that requires system integration (meaning: synchronising data for the same user in multiple systems) has custom needs for user registration, and I found this solution the one that suits my need best for two reasons:
I found I reuse a lot of the custom code I wrote from project to project.
It's the most flexible way to integrate data with the other system (in some case I even split data for the user in two custom tables managed by the same module: one that contains custom fields used by drupal only and one that contains the "non visible fields", as you call them. I find this very handy in a lot of scenarios, as it makes very easy to inspect and manipulate the data of the two systems separately.
HTH!
If you're already using the Content Profile module, then I'd really suggest continuing to use it and attach the field to it. You're saving the data when the account is created, and creating a node for the user at the same time isn't that hard. Really.
$node = new stdClass();
$node->title = $user->name; // what I'd use, or you can have node auto title handle the title for you. Up to you!
$node->field_hidden_field[0]['value'] = '$*#$f82hff';
$node->uid = $user->uid;
node_save($node);
Bob's your uncle!
I would go for option 3. Eventually even other modules will store the data in the database against a user. So you could directly save it yourself probably in a more efficient way than those modules.
Of course depending on the size of the data, you can take a call whether to add a new column in the users table or to create a new table for your data with the user's id as the foreign key.

Resources