Hi all.
I am working on a Gaming portal. I am a PHP developer, and am using Drupal 6.8.

The basic layout would be that I would have an index page listing all available games.
This list would be fetched from the database.

Clicking on any game would take me to a Game Play page which is of the Page type content.
Here I'd load the requested game based on just the url requested for.
If this doesn't make sense here's what it'd be like:

Index Page:
Game 1 (link --> games/game-1)
Game 2 (link --> games/game-2)
Game 3 (link --> games/game-3)

Game Play Page:
Here, depending on the requesting url (games/game-1, games/game-2, games/game-3, etc.) I want to load the corresponding game, by fetching the game's .swf file, again from the database.

Now the problem is that, I want all those urls (games/game-1, games/game-2, games/game-3, etc.) to take me to the same Game Play Page, but at the same time figure out a way of reading the game's name (game-1, game-2, etc.) from the url.

Is that possible with just Pathauto?
Or is there some other way of doing it?

Comments

marcvangend’s picture

There are basically two approaches for your case.

You can choose to create one node for each game, containing all data (name, info, swf etc.) for that game. You'll probably want to create a template file (ie. node-game.tpl.php) to control how the node is displayed. You can just use pathauto to create the url's. Technically speaking, they are all separate pages, but from a visitor's point of view, all game pages will be similar.

The other option is more complicated and uses the views and/or panels modules. This might be necessary if the information about a game is spread out over a number of nodes. In this case, you create a view or a panel page with the path 'games'. Now, when you ask drupal for games/game-1, drupal goes to the 'games' page and passes on 'game-1' as an argument for that page. In the view or the panel you will have to specify what needs to be done with that argument and how drupal should collect all relevant data and show it on the screen.

I hope that helps.

pankajchand’s picture

hi

I have similar kind of query. I created two cck content types Owner and Product. Each Product has reference to one of the Owner type.
Now what i need to do is that on every Owner's page I need a link or tab to a chart node or page. This page should be able to get the information of all or some fields from all the Products that refers to that particular Owner.
i.e. the chart page or node should know that the user has reached there from a particular Owner's page. Is it possible using views and panels.

help please

thanks
regards
Pankaj

marcvangend’s picture

Pankaj, your question is only slightly related. Please open a separate thread for your question and choose a good title, this will motivate more people to read your question.

paganwinter’s picture

^^^
Thanks a lot for the reply...
But my problem has grown a lot more as the day transpired... :)

Need to clarify one other thing:
Are you saying that if i have a url like games/game-1, I can make Drupal treat the game-1 part as an argument to the landing page?
Can't this be done without Views or Panels. I really don't want to depend on additional modules.

What I have done right now is:
Created the links as games/game-1, games/game-2, etc.
I then created a generic Game Play Page with path 'game_play'.

I then edited my .htaccess file as follows:

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico

# To escape 'games/game-name' type URLs
  RewriteRule ^games/(.+)$ index.php?q=game_play&game_path=$1 [L,QSA]

  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

Added one more rule before Drupal's own rule, to convert all games/game- URLs to game_play?game_path=

e.g.:
games/game-1 becomes game_play?game_path=1

I know the rule looks very complicated, but this is the only thing I could get to work.

All was well till I did a ctrl-F5 on the page and the whole damn site was broken, till I commented out my rule from .htaccess.

I am back at square one now :(

marcvangend’s picture

Generally speaking, but also in your specific situation, you shouldn't need to edit .htaccess. Drupal offers plenty of options to create pages that respond to the right url's.

Drupal url's work like this: all requests are in fact handled by www.yourdrupalsite.com/index.php. When you go to www.yourdrupalsite.com/games/game-1 (a "clean url"), what you get is the same as www.yourdrupalsite.com/?q=games/game-1 (not a "clean url"), which is in fact equivalent to www.yourdrupalsite.com/index.php?q=games/game-1. Now it's up do drupal to handle the 'games/game-1' part. Drupal will search for a page with a matching path. First, Drupal checks if there is a page with path 'games/game-1'. If it exists, it is displayed. If not, drupal cuts of the 'game-1' part and looks for the path 'games'. If it exists (and in your case, it will), the script which generates the output for that page, can use 'game-1' as a variable.

Now the next question is: where is that script which generates the output for 'games'? That's up to you to decide. It can be a contributed module, like views or panels, but it can also be the node module, part of the Drupal core. You could even write your own module. I can't really tell you which is the best option because it isn't yet clear to me how your games page should work. Maybe you can explain a little bit about how your content is stored, how you (or users?) will be adding data to the site and which information you want to show on a game page.

One last remark: a lot can be done without additional modules. In fact, it can all be done without Drupal! But why would you? There are more fantastic modules out there than you and I could code in three years time. That's the power of open source software. If you choose your modules carefully (is it stable, is it well maintained, is there enough support?) I really believe you're better off using a contributed module than using your own code.

paganwinter’s picture

Thanks again for your reply.

The reason I am skeptical about using modules is that, they are made to be so generic that anyone could customize and use them. I feel that in doing so, performance is compromised. Also The database overhead is something that worries me.
Instead I'd like to know how a particular module works and adapt it to better suit my specific requirements than have it do 20 things that I am not interested in. Just that I feel I am not yet good enough to create 1000s of lines of code myself. That's why I want to learn from the modules, how experienced people would do stuff, and not do things my way.

The way my current setup works is this way:

I have a page displaying a list of games ( along with an image and a link like games/game-1 ).
This is done by simply fetching a list of games (and image file paths) from my own table (say, 'game_details').
Here's the PHP code I am using inside a Page Content type with PHP filter enabled (it's quite raw as I am only testing it yet)

List of Games (URL: /my_game_site/games/)

<?php
$res = db_query("SELECT game_id,game_name,game_path,game_img_path FROM game_details");

while ( $temp = db_fetch_object($res) ) {
  print("<a href='/my_game_site/games/" . $temp->game_path . "'>" . $temp->game_name . " <img src='" . $temp->game_img_path . "'></a><br />");
}
?>

The href attribute comes out to something like '/my_game_site/games/game-1'

Game Play Page (URL: /my_game_site/game_play?game_id=game-1)

<?php
if (isset($_GET['game_id'])) {
  $game_id = $_GET['game_id'];
  $qry = "SELECT game_name, game_file_path FROM game_details WHERE game_path='" . $game_id . "'";
  $game = db_fetch_object( db_query($qry) );

  print("<b>" . $game->game_name . "</b><br />");
  print("<embed src=\"" . $game->game_file_path . "\"  width=\"640\" height=\"480\" />");
}
?>

As you can see I am using the 'game-1' part (from /games/game-1) as a GET query string argument to the 'game_play' page.
Hence my URL Rewrite Rule wet like:

  RewriteRule ^games/(.+)$ index.php?q=game-play&game_id=$1 [L,QSA]

So that when the games/game-1 page was requested, I was doing part of what Drupal's own rule(RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]) was doing. I am retaining the original rule too though, for the rest of the pages.

As I mentioned earlier, this worked fine till I did a control refresh of the page. Then all formatting of the page was gone, but it still was functioning as expected (showing up the correct game in the game_play page).

Also can you elaborate on this?

First, Drupal checks if there is a page with path 'games/game-1'. If it exists, it is displayed. If not, drupal cuts of the 'game-1' part and looks for the path 'games'. If it exists (and in your case, it will), the script which generates the output for that page, can use 'game-1' as a variable.

How can I make my /games/ page use game-1 as a variable? That is, without the URL rewriting?

marcvangend’s picture

If it's performance you're after, you are right that you shouldn't use too much modules. Custom modules could perform better than generic modules. That being said, did you know that 80% of the end-user response time is spent on the front-end (source)? That means that optimizing your web server, database, modules, queries, cms configuration etc. only influences 20% of the total page loading time.

Anyway, back to your original question. If I were you, I would use the CCK module to create a 'game' content type, so you get a single node for each game, containing all details. I would use the Views module to generate the list of games with the links and images. I am convinced that most experienced Drupal developers would tell you to do it like this, but it's your party, so you don't have to.

If you want to use your own code, the 'proper' way is to write your own module. Let's look at a very simple module, so you can see that a module can be les than 1000 lines of code. This would be the code of helloworld.module:

<?php
/* implementation of hook_menu() */
function helloworld_menu(){
$items = array();

  $items['helloworld/%'] = array(
    'title' => t('Hello world'),
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

function helloworld_page($name) {
  $output = '<p>'.t('Hello world!').'</p>';
  $output.= '<p>'.t('Hello').' '.check_plain($name).'!</p>';
  return $output;
}
?>

You see two functions. The first is an implementation of hook_menu(), which means that it provides data for drupal's menu system. In human language, it says "When the path 'helloworld' is requested, ask the helloworld_page function for the page content and pass on the first argument to that function."
The second function generates the page content. It takes the argument passed on by the menu system and puts it in the $name variable. It creates a string of html code and returns it. Some strings are wrapped in the t() function to allow for translation. The $name variable is run through the check_plain function to prevent malicious input. Done!

If you want to install this module and play with it, paste the code above in a textfile called helloworld.module. Create another file called helloworld.info and put the following lines in it:

; $Id$
name = Hello World
description = Simplest module ever.
core = 6.x

Put those two files in a folder called 'helloworld' and put the folder in your modules folder (probably sites/all/modules). Now you can enable the module on the admin/build/modules page. Go to www.example.com/helloworld/paganwinter and see it work.

Even when you decide to create your own games listing with a custom module, I strongly advice you to use Drupal nodes with CCK to enter the data. Nodes are such a strong concept in Drupal, you would lose a lot of compatibility and future options if you didn't.

paganwinter’s picture

Thanks a ton again :D

I tried it out but got an "Access Denied page instead".
I am now going through the Modules Development Tutorial now.

By the way, I found this:
http://api.drupal.org/api/function/custom_url_rewrite_inbound
But am not very sure how to use it.

For the time being I'll start out slowly with module development and then proceed to other things.

Just one other thing; you said "use Drupal nodes with CCK to enter the data"
But if I have a custom node that will be fetching the data from the database to display it's content, how can/will I use CCK?
I initially did use CCK to have something like this:

Body (included the PHP code to fecth list of games)
Ratings (cutom CCK field to show the ratings button)
Favourites (cutom CCK field to show an 'Add to Favourites' button)

Then I came across this article.

Still have miles to go before I sleep :)

marcvangend’s picture

Hmm... I'm not sure why access is denied. Are you sure the module is enabled? Are you logged in as user no.1?

I think you don't need any url rewriting. Don't rewrite url's, just create menu callbacks so the url gets linked to the right function.

If you use CCK, the data entered in the CCK fields is automatically added to the node object when you load it using node_load(). CCK takes care of creating a nice node create/edit form, but it also makes sure that every other module that loads a node, can use the CCK data.

"Then I came across this article." Don't worry about it. The article is totally right: you shouldn't put php code in content. That's why you should write a module for your needs.

paganwinter’s picture

Thanks a lot for all your support.

Access was probably denied because I had not mentioned any permissions for the module (using hook_perm()) and neither was I specifying any permissions in the hook_menu using 'access arguments'.

I now have what I wanted:
A page listing all games from the database and than a Game Play page on which the actual game selected will be loaded, for playing. And the URLs are taken care of too.

Some other queries that I have:

  • I found this link describing how to create a custom node type.
    Do you think it's relevant for my project too? Or can I do without it at all.
  • I need to include an option of having comments enabled in the Game Play page, for the current game being played. I guess I can't straight away use the core comment module to do that. I would need some way of passing the current game's info along with the comments and also while fetching the relevant comments for a particular game. Any ideas how I should go about doing this?
marcvangend’s picture

I'm glad you got it working. Strange that it did work for me...

The link you're referring to dos not describe how to create a custom node type, but it describes the l() function, which generates html code for links. Anyway, I think CCK is the way to go to create your custom node type.

Why do you think you can't use the core comment module? If you have enabled the comment module, you can enable comments for your custom content type as well.

paganwinter’s picture

What I have done is created a module which just fetches a list of games from the DB and displays it;
and the for URLs like games/game-1, it fetches the game's (game-1's) data and displays it on the screen.

So I still don't exactly have a custom node/content type. It's just some HTML elements generated by my custom PHP and displayed on the screen.

marcvangend’s picture

Then start creating proper content types! I'm sorry that I keep repeating myself, but I really think you should stop trying to code everything yourself and start using nodes and CCK. Why are you using a framework/CMS like Drupal if you don't use it? If you use nodes, there is a huge number of modules you can use to add additional functionality. Comments, for instance. The Drupal community has already done a lot of work for you, it's just lying there, ready for you to pick it up and use it.

paganwinter’s picture

Soory, here's the correct link

I was using the comments module earlier, when I was was putting all my PHP into a Page type node.

I feel my problem here is that if I go by the content type method, then I am left with having to create just 2 types of content, and one actual page of each type:

Games list Page
AND
Game Play Page

What is the purpose of creating a new content type when I am not going to update/create new content. I am planning on making entries to the database directly. I currently have just 2 pages, with dynamic content in them.

Then there is an altogether different approach that I could use:
Create a 'game' content type, Have the admin enter new games via the admin form for the 'game' content type.
That would again mean that if I have 100 games, I'd be storing nodes for all 100 of them.

That is the whole reason I took the current approach.
Another thing is that the users won't be contributing games to the site. That is another reason I don't need a whole new content type.

Instead I am relying on the assumption that there is some way that I can enable the comments module to show up on my new module page.

I really don't have the time, right now, to go try to figure out what all possibilities CCK makes available. I do have a vague idea that it can be done with existing modules, but right now is not the time. Maybe once I have got enough expertise, yes.

I have come across many comments in the forums saying that Views is not very good with query optimization. This again makes me not want to completely rely on modules, at least as long as I (think) that I can do things in a better way.

marcvangend’s picture

When you're creating custom node types, you would only need the 'game play page' type. The games list is not a node, that page is dynamically generated by your custom module and loads it's data from the nodes in the database.

Then there is an altogether different approach that I could use:
Create a 'game' content type, Have the admin enter new games via the admin form for the 'game' content type.
That would again mean that if I have 100 games, I'd be storing nodes for all 100 of them.

Well, that's exactly how nodes are supposed to work. But is that a problem? 100 isn't that much - this thread is node #354910 on Drupal.org...
If you're planning on entering data in the database manually, the node system isn't practical, because it uses several tables for a single node. But I don't understand why you would want to edit the database manually if you can have a nice admin interface. The fact that users won't be contributing is not a reason to abandon nodes. Nodes are primarily a method standardize the storage of content in the database and to share this content between modules. Developers and admins benefit from that too.

Reading your post, I see that you rather rely on unfounded assumptions (that you could apply node comments to a page that is not a node) than on proven technology that is very easy to use (CCK). You don't have to follow my advice of course, but if you really want to do it your way, there's no point for me to keep replying to your questions, sorry.

paganwinter’s picture

I can understand your frustration. I must be really getting on your nerves :P
You have to forgive me , cos I am still a newbie here, absorbing everything I can.

The thing is now I better understand how Drupal is supposed to work. Hence I guess it's time for me to rethink my approach.
My main doubt is: "With respect to my particular case, is it better to have a single dynamic page (node) that displays only the requested game or have individual semi-static nodes for each game".

Here's what I think, would be doing it the 'Drupal' way. Please correct me if I am wrong:

I need to create a Game type node.
This node would have 3 regions(fields, if you may), for the time being:

  1. Game Window
  2. Ratings button
  3. Add to Favourites button

I want all 3 fields to be of PHP type.
As part of the admin interface, It should only allow the admin to enter details of the game (game's image, Name, .swf file etc.).
The other 2 fields need not have admin intervention, as such.

But while viewing, I want all 3 fields to just fetch the game's details from the DB.

So, say, my game is now a content type (attributes would be - Name, image, .swf file, ratings), when I am at a particular game's page, it's just showing me the data that is stored.

In short I need a complicated Content type to store the game's details and the a similar method to actually output it on the screen.
Comments would be easily taken care of then.

marcvangend’s picture

I can see that you're trying hard to understand and learn, I just worried that I would have to keep saying 'CCK' all the time.

If I understand correctly, you ask if a game-play page should be a single node page or if it should consist of multiple nodes combined in one page. My answer would be: use one single node for each game. If there is partial content that you would like to re-use on multiple game pages (for instance: details about the author of the game, when one author has many games), you could create a separate content type for that and link those nodes to the game nodes.

A couple of messages ago, you linked to an article that said you shouldn't use php in content. Let's stick to that principle as long as we can, OK? There are lots of small modules that extend CCK, so you probably don't need php fields. Let's have a look at your 3 fields:

Game Window: Is this a flash file? What kind of data doe you want to enter here?
Ratings button: use the excellent fivestar module, http://drupal.org/project/fivestar
Add to Favourites button: do you mean favorites in the user's browser, like this one http://www.web-source.net/javascript_add_favorites.htm? That code will be the same for every node, so you don't have to put it in a field, you can add it to the node template.

If you're going to do this the drupa lway, don't think of these fields as code that is fetching data from the database. Creating a content type is creating your data model. The node form is not an interface to write code, it is an interface to add data to your site.

Once the data is stored in nodes, you are right that the game's page will show you the data that is stored. If you want to change the way it is presented, or want to manipulate the data defore it is rendered, that's where the theming begins. Don't forget that a CMS like Drupal always separates content, behavior and presentation. Nodes are your content, modules define the behavior, theming controls the presentation.

paganwinter’s picture

I think we need to move this to a different topic now.

Here's a little more detailed description of what I am trying to do:

These are the fields that I want to display on my Game Play Page:

Title of the Game (Plain Text)
The actual Game (the game's .swf file)
Help for the Game (Could be a combo of Text, Images or another .swf file)
Ratings (I guess Fivestar would suffice)
Add to Favourites (this has nothing to do with the browser's bookmarks. It would be a way that the logged-in user can add the game to 'his Favourites' - think of it as extending the user's profile to include a section having a list of his favourite games. I am planning on a table which would store user-game_id pairs, though this doesn't seem the most appropriate way of doing it. Any suggestions?).
Comments (Will be enabling Drupal's own comments, though later on I'd have to tweak it or find some module which lets users report abuse).

Are there any readily available content types to use with CCK for the above fields?

marcvangend’s picture

There are no 'ready made content types' for CCK. There are a lot modules that make different types of fields available (see http://drupal.org/project/Modules/category/88). You construct your own content types by adding the fields you need.

So, considering the fact that you want as little extra modules as possible, you could do this:
- Title of the game: just use the node title.
- Game's swf file: use the upload module (drupal core). This will allow you to attach the swf to the node. The embedding in your page can be taken care of in the node template.
- The help part is a little more complex, because you want the freedom to use text, images and flash. A textarea would be the easiest, if you don't mind typing some html yourself.
- Ratings: Fivestar it is.
- Add to favorites: have a look at Session favorites (http://drupal.org/project/session_favorites) or Favorite Nodes (http://drupal.org/project/favorite_nodes, review at http://drupalmodules.com/module/favorite-nodes?#reviews).
- Comments: Drupal core is fine. For abuse reporting, see the Abuse module at http://drupal.org/project/abuse (although the Drupal 6 version is not final yet).

To make swf embedding easier (both the game file and optional help swf's) you could consider using swftools (http://drupal.org/project/swftools).

paganwinter’s picture

Thanks once again for the suggestions.

I have made quite a headway on this now...
Only problems being that Favorite Node and Abuse both are in Development snapshot as of now... :(

The embedding in your page can be taken care of in the node template.

Can you elaborate a bit on this?
Is this what you're saying:
If I create a custom content type, then I can go and modify the type's template file to display the content as I want.

On top of that, is the following possible using CCK?
I would like to input certain no. of parameters when I am creating a game page - Name of the game (The title field should suffice), .swf file path (just text filed), image file path (another text field), etc.
But when I am displaying the content I want to have control on the parameters I entered while creating the page.

I would like to convert the .swf file path into an HTML tag, probably not display the image, etc.
But have sort of a handle on where all the data got stored.
Because I need this when I am displaying a user's favorites. I'd like to customize the default favorite node output to also include an image of the game along with the link to the game's node.

So basically, my 'Game' content type should enable be to put a certain no. of 'things' into the database, but allow me the freedom to call upon those 'things' as and when I want them, including while displaying the actually node.

I know I am asking for too much...

marcvangend’s picture

You theme probably contains a file called 'node.tpl.php'. If not, Drupal uses the default node.tpl.php (http://api.drupal.org/api/file/modules/node/node.tpl.php/6/source) to render the output of a node. If your content type is called 'game', you should duplicate your node.tpl.php as node-game.tpl.php. This will automatically override node.tpl.php as node template for nodes of the type 'game'. There are lot of variables available in node.tpl.php; the complete node object (including the data entered in CCK fields) is one of them. This means that you can use html and php to output whatever you want. For instance, if you have a field called field_image_url, you could add this to the node template:

<img href="<?php print $node->field_image_url[0]['value']; ?>" alt="my image" />

(This is just an example by the way, there are more sophisticated methods to add images to content using CCK.)

WorldFallz’s picture

Another option for favorites could be the http://drupal.org/project/flag module which is very flexible and has official, though beta, releases.

===
"Give a man a fish and you feed him for a day. Teach a man to fish and you feed him for a lifetime." - Lao Tzu
"God helps those who help themselves." - Ben Franklin
"Search is your best friend." - Worldfallz

paganwinter’s picture

Thanks for the suggestions.

Marc - I found just what I had wanted - Contemplate.
It's just purrrrfect for what I want to do. It allows me to specify a custom template for outputting a particular content-type, without having to touch the template file.
So I get a window where I can override stuff like:

<?php
  print $body;
?>

to

<?php
//  print $body;
  print $my_custom_field_only;
?>

I also have access to all the node variables here. It's a great module.

@WordFallz
Will try out the Flag module.

marcvangend’s picture

Contemplate is nice, I know. I didn't mention it because you said you prefer to use as little modules as possible...

One word of advice: use disk-based contemplates. I have experienced that it makes maintainance easier, because you can use version control systems like SVN and CVS. Another advantage is that you can use a good text editor (with code highlighting) to edit the php, so you'll make fewer mistakes. Finally, when your contemplate causes a php error, you may not be able to reach the edit page anymore. With disk based contemplates, that's no problem.

paganwinter’s picture

Thanks, will remember that.

I am also using Flag with Views for a user 'Favorites' section, wherein users can add certain games as their favorites.
Now that most of the content related things are taken care of, I want to start working on the User Profile.

I am trying out Advanced Profile Kit right now. But it doesn't seem to be very flexible.
I need to display a list of friends (built-in), Recent Visitors (built-in), Favorites (Need to figure out how), User Avatar (built-in, but I want to extend it).
Basically I need more control on what gets displayed in the User's Profile. Any good resources on customizing APK?

marcvangend’s picture

I have no experience with APK. Maybe it's better to start a new thread for this. While you're investigating user profile solutions, also have a look at http://drupal.org/project/content_profile.

paganwinter’s picture

Ok. Will do that...

Thanks a million for all the help you've provided so far... :D

aakanksha’s picture

k

bartl’s picture

(Re)

Though there are other solutions, the simple fix to the "access denied" problem is to add this entry in the $items['helloworld/%'] array:

    'access arguments' => array('access helloworld content'),

That takes care of the access rights for ordinary page view all by itself.

bg1’s picture

I saw that you have given advice a few times on building a first module and getting it to work.

I created files to match the above:
helloworld.module in folder: htdocs/drupal/sites/all/modules/helloworld
helloworld.info in same folder

I don't know if it is needed, but I changed the owner for the helloworld folder from root to 1080 and also gave all permissions.

drwxrwxrwx 2 1080 1080 4096 2009-12-13 10:54 helloworld

I also change the owner and group for both files to 1080, but I left the permissions the way they were because I saw the modules in other folders also had those permissions.

-rw-r--r-- 1 1080 1080 74 2009-12-13 10:53 helloworld.info
-rw-r--r-- 1 1080 1080 450 2009-12-13 10:53 helloworld.module

I enabled the module in drupal (and saved the configuration).

I could not set any permissions in Drupal re. this module because when I go to Permissions under User Admin there is nothing referring to this module.
When I go to the administration by module page, the module is not listed.

when I try to run the module: localhost/drupal/helloworld I get the following:

Page not found
warning: Cannot modify header information - headers already sent by (output started at /opt/lampp/htdocs/drupal/sites/all/modules/helloworld/helloworld.module:23) in /opt/lampp/htdocs/drupal/includes/common.inc on line 148.
The requested page could not be found.

Continuing your example to show one exactly how to embed the module into one's Drupal site would be greatly appreciated.

Thanks in advance.

marcvangend’s picture

Hi William,

Usually, changing owners and/or permissions on module files and folders is not needed. You are right that no specific permissions could be set for this module. Modules don't have to define their own permissions, it's optional. The module also does not appear on the administration by module page, because it does not define it's own settings pages. After all, it's supposed to be a simple module!

What you're seeing, is a mixture of 3 problems.

1) For the 'headers already sent' part, see http://drupal.org/node/1424.

2) As paganwinter pointed out, I forgot the access arguments in my code. After adding that, your module code would look like this:

<?php
/* implementation of hook_menu() */
function helloworld_menu(){
$items = array();

  $items['helloworld/%'] = array(
    'title' => t('Hello world'),
    'page callback' => 'helloworld_page',
    'page arguments' => array(1),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

function helloworld_page($name) {
  $output = '<p>'.t('Hello world!').'</p>';
  $output.= '<p>'.t('Hello').' '.check_plain($name).'!</p>';
  return $output;
}

Note that, to prevent 'headers already sent' errors, Drupal coding standards strongly recommend to leave out the php closing tag ?>.

3) This module is not supposed to do anything localhost/drupal/helloworld, so the "page not found" is correct. Looking at the hook_menu implementation, you see that the module registers the 'helloworld/%' path. The %-sign is a placeholder for an argument in the url. If no argument is given, the url does not match the pattern from the menu item, so Drupal will return page not found. Make sure that points 1) and 2) are fixed and then go to localhost/drupal/helloworld/your_name.

bg1’s picture

Thanks! I will try this. I think the main problem was not understanding 'helloworld/%' required an additional argument.

This is because I was following an example and not understanding the example I was following.

When I got a version of helloworld module to work that did not have a menu_hook, and I went to blocks under administration, the module was there and I was able to assign it to a region as though it wore a block. The weird thing, however, was that it showed up in the first block within that region rather than standing on its own.

I now understand that the concept of hooks is key to working with custom modules (at least I am thinking that now). But I don't understand how the hook enables me to tie a module to a menu item or a page or a block, etc. Any advice in that direction would be greatly appreciated.

If there is any good beginner documentation, that would help. What would be the best online documentation (preferably printable) regarding hooks and the basics of developing custom modules.

I am an experienced developer but for last 10 years have written mostly SQLSvr stored procedures and classic ASP. I have no experience with PHP, but a number of years ago I taught programming and have programmed in many languages over the years so I am confident I will have the basics of the language down in a few days. The big problem is understanding the functions. In my case, I am planning to develop web service client modules that I wish to tie in to Drupal Views (essentially I want to be able to define certain views as virtual views that when they execute, instead of firing a query against the local Drupal database, will call a remote web service and then map the returning results tot he view and display according to the views standard display rules). Can you advise of any work already being done in this direction in Drupal modules or functions/libraries for PHP that would support such a module?

Thanks again for your assistance.

Bill

marcvangend’s picture

You are right, understanding the concept of hooks is very important. There are many hooks in Drupal core; see http://api.drupal.org/api/group/hooks/6 for a list. To get started with the most common Drupal hooks, the api documentation provides a couple of example modules; see http://api.drupal.org/api/search/6/example.module. Of course there is also the 'Developing for Drupal' section in the handbooks: http://drupal.org/contributors-guide.

hook_menu has nothing to do with publishing blocks. You wrote "When I got a version [...] standing on its own" but I really don't understand what happened there. It does not sound logical.

Modules can provide blocks by implementing hook_block, as you can see in block_example.module at http://api.drupal.org/api/drupal/developer--examples--block_example.modu....

By implementing hook_menu, you're basically routing a url to a php function (the menu callback). Usually, that menu callback returns main page content. This main content is embedded in the page template, together with other page elements such as blocks and the logo.

Personally, I have little experience with integrating external services the way you describe. I recommend drupalmodules.com (search for services: http://drupalmodules.com/search/node/services) when looking for Drupal modules; it lists all modules you find on drupal.org, combined with ratings and a good search interface.

bg1’s picture

Thanks for the additional input.

Since I am trying to really understand how Drupal works, I would like risk trying you patience and describe a possible scenario and you can tell me if I am close or not.

My guess as to how Drupal is functioning with regard to modules, is as follows:

Somewhere in the Drupal database there is a table of modules with attributes that include the hook reference, a flag indicating whether or not it has been enabled and a path to where the module is located (although, having said this, I don't see a Module Table in the Drupal database - based on a Drupal 4.7 Schema diagram I found - could it be that Modules are also Nodes and everything else in in the Files table?).

In addition, within the existing Drupal code, there are predefined hooks that are essentially function calls. These function calls call a function that retrieves all the module information from the database that refer to that hook and then tries to execute the module callback function. If that succeeds it will return whatever content it returns to the main page processor that will combine that data with whatever else is to go on the page and send it to display.

Am I close?

Thanks for your patience with a newbie's learning curve.

marcvangend’s picture

Yes, you are close. There is a table in the database that keeps track of all available and installed modules: the 'system' table.

I appreciate your eagerness to really understand Drupal, so please don't apologize and keep asking.

Regarding hooks: at any point in code (either in core or in a contributed module) a module can 'ask' for additional input. This asking is done by 'implementing a hook', which means that all functions are called that match a specific naming convention: [modulename]_[hookname] (ie. user_menu when the user module invokes the menu hook). The input of all modules is collected and merged into the process. For instance, when hook_menu is invoked, all modules are asked if they have any menu items to add. Their return values are processed by the module that was invoking the menu hook.
'Implementing a hook' means that you write a function in your module that follows the naming convention, accepts the parameters for that hook and returns a value in the expected format.

It is not registered which module implements which hooks; when a hook is invoked, Drupal simply checks every installed module to see if it implements that hook.