Field data in one table, not many. for drupal7 - drupal

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

Related

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!

Drupal List View for data entry to multiple records

I would like to create a data entry form in Drupal 7 that is similar to Filemaker's List View. List View is a view that contains many records on a page. When Submit button is clicked, data entered in the fields will be assigned to the individual records.
For example, I have a list of students' names and a column field of grade type. The student's name will be created from Drupal View's filtering, but the grade field will be empty waiting for me to key in.
What is the proper Drupal's module that can enable this functionality? Or what can I do to create this functionality.
This approach is closer to your original request, im testing this out now and I think it should more than do the trick, much more interestingly too.
http://drupal.org/project/slickgrid
Edit:
I highly recommend trying this its awesome!!
A couple quick tips
Be sure to also install http://drupal.org/project/title so you can reset the title (make it a field), Basically with this editor you can only edit actual fields, so same goes for location module, you'll need to use the field option rather than node option.
One possible downer, at least for my site, it appears the drupal module does not support jquery 1.7 which my site uses, so a few buttons etc don't work as expected, also the drupal module does not support the latest slickgrid release either. I'd like to look into fixing that but I dont have the time just yet, possibly someone will before long. If jquery 1.7 is not required for your site then none of that will be a problem for you.
I just figured how to do something similar, although I went about it a different way then I think would be the most desirable, at any rate what I did works perfectly for me at the moment.
What I did...
Used a google docs spreadsheet for data entry, exported a CSV file, then used Feeds module to Import and Map it to my desired content type. I was even able to get location, taxonomy & image fields to map.
Modules & Stuff Used...
Feeds http://drupal.org/project/feeds which also includes Feeds
Importer, you'll want to read through all the instructions to be sure
you understand the import methodology, I could never explain it all
here!
Feeds Tamper http://drupal.org/project/feeds_tamper , I used this to
explode the cell which had a | separated | list of taxonomy terms (dont use comma), the
nice side effect is if the term doesn't exist it creates it for you!
Spreadsheet - Personally I created a Google Docs Spreadsheet, any type
will do. This spreadsheet has every field you want to map to fields
in your content type.
"More Better"
Currently I am on the hunt for a simple backend UI way to do this, but this is what I've settled on for now. I just couldn't imagine hand entering hundreds of nodes, page submit after page submit! I will post back if I figure another way to do it. Good luck!
I have just started with
https://www.drupal.org/project/editableviews
which enables the creation of views where all the fields are editable, including when no data exists in the related entity. At the first url is also documentation.
There a screencast which shows more
https://www.youtube.com/watch?v=g_D4z4Bw6iw

Drupal 6 - make a module for every block of dynamic information?

I have a Drupal 6 website with about 20 pages. Inside every page, I need to create a lot of widgets with information either stored inside the database or from external web services. Most of the time, a "view" (from the view module) is just not enough to solve the requirement.
Up until now, any time I need such a widget, I create a new module which implements hook_block. Then, I drag and drop this new module inside the panel I want. I will need to create about 20 modules. This works pretty good. However, I'm not sure if this is the correct-drupal-strategy and I would love to receive some feedback from experienced Drupal developers.
A module can expose as many blocks as you want (in theory, admin/build/blocks will teach you otherwise ;)).
Have a look at the documentation of hook_block(), you just need to extend yours to return multiple block infos and then decided which one to show based on the $delta.
So you don't need 20 separate modules, maybe 2-3 and group the blocks somehow together because just a single module might be hard to maintain. The thing is that every single module makes your site a tiny bit slower (at least one more file to load, module_implements() needs to loop over every module for every hook and so on).
Without more information , it's hard to give any better advice. Maybe you could expose your data to views, or write a views plugin to display it in the way you want it, or...
Although Berdir's answer is pretty good, I'm impressed there's no link to any documentation in it. hook_block is meant for several blocks, and they can share functions that build their content. The API page is good, the example it gives defines two blocks at once.
You should notice each defined block has a delta (a key in the $blocks array). You can have dynamic deltas and use values in it to fetch data (passing a nid or uid and getting related content, for example).

moving database schema over to 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.

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