2

I am trying to integrate a custom website into the drupal 7 system. On this website there is a lot of user interaction with buttons, database queries, ajax loaded elements, … . I need to get the the global user variable on this page.

My first question: What is the best way to integrate the webpage?

My first attempt was to create a content type (node—myPage.tpl.php): I got permission problems using ajax, so I separated the code into two files (node—myPage.tpl.php and myPage.php). In the node—myPage.tpl.php I only included myPage.php. But now I have the next problem using ajax (for myPage.php). I cannot get my global user variable.

My second attempt was to create a custom module. So I created a callback page. But I think I have to make a renderable array. I want to avoid this because myPage.php has over 3000 lines of code. And I don’t think jquery ajax will work as it should.

Is there an easy way to integrate a custom website into the drupal 7 system with access to the drupal api (user variable, functions)? I also prefer to keep the custom page in a php file, not into database.

  • 2
    "But I think I have to make a renderable array." - false. You should do it, but Drupal will swallow string with html markup pretty well, too. Dirty way, but works. – Mołot Dec 23 '13 at 7:51
  • +1 for not needing a render array. Personally for extremely custom pages I don't think it's that wrong or dirty to return a string anyway. – rooby Dec 23 '13 at 8:33
  • @rooby For me dirty ≠ wrong. But clean way is to return renderable array other modules can interact with by using hook_alter. Not always it is needed, but always it is cleaner. Of course often it's not worth to implement clean way, but it's good to remember what you do is not pure ;) Or that's how I see it. – Mołot Dec 23 '13 at 8:52
  • @Mołot, rooby: I think there is truth in both of your comments. The flexibility of render arrays is great, but most useful in contrib modules. For a completely custom page, you don't need alter hooks because you can just go in and change the code. That's why I proposed a "hybrid" solution in my answer, combining some advantages of render arrays with the time-saving efficiency of reusing a working script. – marcvangend Dec 23 '13 at 12:51
1

The way you are supposed to do it, is to create a module, with proper hook_menu and all that. That's the only way to really plug your script into Drupal routing system. And you don't need renderable arrays, if you are OK with quick and dirty job, your functions may return strings, too. If in doubt, just see Examples for Developers project, it has it all documented pretty well.

You may do the other way around. Drupal's standard .htaccess is set up the way that makes Apache execute any php file that is there, and only if there is no file it makes Apache to call Drupal's index.php. So instead of integrating your one-page app into Drupal, you may bootstrap Drupal into your one-page app. It was already asked and answered here, so I don't think it's worth to repeat all of it. Key point is, that with this code:

/**
 * Initialize Drupal
 */
define('DRUPAL_ROOT', '/var/www/clients/client1/web15/web');
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
require_once DRUPAL_ROOT . '...'; // include required module files to work with here

drupal_override_server_variables(array('url' => 'http://www.example.com/batch.php')); // trick drupal to do bootstrap
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);

set_time_limit(4600); // adjust for your needs
ini_set('memory_limit', '3524M'); // adjust for your needs

at the beginning of your one-page php file, you can assess Drupal data and functions all you want, but avoid Drupal routing and render flow.

  • You are my heroes. That's exactly what I was looking for. The bootstrap thing works fine. Also thanks to all other comments. When I have more time I will make the cleaner version with renderable arrays and do a performance comparison. – Fox0815 Dec 23 '13 at 19:21
5

A custom module with a menu callback is the way to go. In general, themes and tpl.php files should only control what your site looks like. Modules should control what your site does.

I understand that you don't want to refactor your code completely and turn everything into render arrays. Fortunately, you don't have to. You can create a string of html and put it in a render array like this:

// Generate your html.
$html = '<p>Hello world!</p>';
// Wrap it in a render array.
$output = array (
  '#markup' => $html,
);

Now, this is the really simple version. I do recommend that you take advantage of some of Drupal's features.

First of all, if you didn't already do so, I would create separate menu callbacks for the ajax requests. If both the rendering of the page and the ajax requests are handled by the same menu router, you might get in trouble when Drupal starts caching things.

Second, I would take add all javascript (and possible css) to the page using the #attached property of your render array. This also allows Drupal to cache (parts of) your page without breaking things. Assuming that your module is called "mymodule" and your javascript is stored in mymodule.js, your render array could look like this:

$output = array (
  '#markup' => '<p>Hello world!</p>',
  '#attached' => array(
    'js'      => array(
      drupal_get_path('module', 'mymodule') . '/mymodule.js',
    ),
    // If your output requires certain CSS rules, regardless of the theme
    // that is used, add a CSS file like this.
    //'css'      => array(
    //  drupal_get_path('module', 'mymodule') . '/mymodule.css',
    //),
  ),
);

Your Answer

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

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