モジュールからhtml.tpl.phpオーバーライドを発行しますか?


8

提供されたモジュールからのページの出力をオーバーライドして独自のhtml.tpl.phpを発行し、テーマからの出力を効果的に制御する方法はありますか?

独自のログイン/登録エクスペリエンスを作成するためにこれを行いたいのですが、HTMLレベルのテンプレートではなく、ページレベルのテンプレートのみをオーバーライドするように見えます。印刷モジュールがこれを実行しているように見えますが、それはそれに取り組む方法ですか?


今すぐ具体化する時間はありませんが、ユーザー/ログインパスのを独自のバージョンのhook_menu_alter()に変更するのに使用できると思います。画面に何をレンダリングするかを完全に制御できるはずですが、適切なヘッダーを自分で設定する必要がありますdelivery callbackdrupal_deliver_html_page()
Clive

ええ、それは私が向かっているところですが、あなたがそのすべての脚仕事をする必要があるかどうかはわかりませんでした。
Kevin

正直に言うとそれを一周する方法があるかどうかはわかりませんが、コアからの良い例は、ajax_deliver()関数と同じです$page_callback_resultdrupal_html_deliver_page()、処理方法が異なります。テーマエンジンが巻き込ま前にプロセスに意味のある方法で、任意の更なるダウンを中断することができるかどうかはわからない
クライヴ

html.tpl.phpの出力を変更する特別な理由はありますか?テンプレートファイルの出力内容を変更する多くの関数があります。
kiamlaluno

@kiamlaluno、これは興味深い質問です。テーマエンジンが関与する前に、Drupalページのレンダリングを停止する方法も探しています。目的は、JSON出力またはOFFのときにViews Datasourceによって提供されるものと同じようにページ(ある種のWebサービス)をレンダリングすることですusing_views_api_mode
Sithu

回答:


4

この回答によると、ページコンテンツを返すのではなく、メニューページコールバックでページコンテンツを印刷するだけで済みます。

Drupalのデータベースからデータを取得したり、PHPで生成したりするには、完全なレイアウトレンダリングなしでデータを出力するページコールバック(カスタムモジュール内)が必要です。これは、ページのコンテンツを返すのではなく、ページコールバックで直接印刷することで簡単に実行できます。

印刷モジュールはこのように印刷用ページを実装したと思います。以下は、モジュールのコードスニペットです。

function print_menu() {
  $items = array();

  $items[PRINT_PATH] = array(
    'title' => 'Printer-friendly',
    'page callback' => 'print_controller_html',
    'access arguments' => array('access print'),
    'type' => MENU_CALLBACK,
    'file' => 'print.pages.inc',
  );
  ........   
}   

/**
 * Generate an HTML version of the printer-friendly page
 *
 * @see print_controller()
 */
function print_controller_html() {
  $args = func_get_args();
  $path = filter_xss(implode('/', $args));
  $cid = isset($_GET['comment']) ? (int)$_GET['comment'] : NULL;

  // Handle the query
  $query = $_GET;
  unset($query['q']);

  $print = print_controller($path, $query, $cid, PRINT_HTML_FORMAT);
  if ($print !== FALSE) {
    $node = $print['node'];
    $html = theme('print', array('print' => $print, 'type' => PRINT_HTML_FORMAT, 'node' => $node));
    drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
    drupal_send_headers();
    print $html;
    ......
}

これによると、モジュールはカスタムHTMLテンプレートを使用しますprint.tpl.php。HTMLレベルのテンプレートです。次に、モジュールはを使用してHTMLを取得し、theme('print',...)を使用してブラウザに直接レンダリングしますprint $html;

ここにあなたの目的のための一般的なアイデアがあります:mymodule.module

/**
 * Implements hook_menu().
 */
function mymodule_menu() {
  $items = array();
  $items['mylogin'] = array(
    'title' => 'Custom Login Page',
    'page callback' => 'mymodule_custom_login_page',
    'type' => MENU_CALLBACK,
    'access callback' => TRUE,
  );

  return $items;
} 
/**
 * Implements hook_theme().
 */
function mymodule_theme() {
  return array(
    'mylogin' => array(
      'variables' => array('page' => array()),
      'template' => 'mylogin', // mylogin.tpl.php in your module folder
    ),
  );
}
/**
 * Generate a custom login page
 * @see more in print_controller_html() in print.pages.inc of the Print module 
 */
function mymodule_custom_login_page(){
    $page = _mymodule_login_page_prerequisite(); // get/prepare necessary variables, js, css for the page
    $page['form'] = drupal_render(drupal_get_form('user_login')); // get login form
    // prepare html in mylogin.tpl.php
    // See more in print.tpl.php() in the Print module  
    $html = theme('mylogin', array('page' => $page)); 

    drupal_add_http_header('Content-Type', 'text/html; charset=utf-8');
    drupal_send_headers();
    print $html; // cease Drupal page rendering and render directly to the browser
} 
/**
 * Prepare the array for the template with common details
 * @see more _print_var_generator() in print.pages.inc of the Print module
 */
function _mymodule_login_page_prerequisite(){
    global $base_url, $language; 
    $page = array();
    $page['language']   = $language->language;
    $page['head']       = drupal_get_html_head();
    $page['title']      = '';
    $page['scripts']    = drupal_get_js();
    $page['favicon']    = '';
    // if there is a custom css file for this page
    // drupal_add_css(drupal_get_path('module', 'mymodule') . '/css/mylogin.css');
    $page['css'] = drupal_get_css();
    $page['message'] = drupal_get_messages();
    $page['footer_scripts'] = drupal_get_js('footer');

    return $page;
} 

テンプレート:mylogin.tpl.php

<?php
/**
 * @file
 * Custom login page template
 *
 * @ingroup page
 */
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php print $page['language']; ?>" xml:lang="<?php print $page['language']; ?>">
  <head>
    <?php print $page['head']; ?>
    <title><?php print $page['title']; ?></title>
    <?php print $page['scripts']; ?>
    <?php print $page['favicon']; ?>
    <?php print $page['css']; ?>
  </head>
  <body>
    <h3>This is custom login page.</h3>
    <?php 
    if (!empty($page['message'])):
        foreach($page['message'] as $type => $message):
        ?>
            <div class="messages <?php print $type; ?>">
                <ul>
                <?php foreach($message as $msg): ?>
                    <li><?php print $msg; ?></li>
                <?php endforeach; ?>
                </ul>
            </div>
        <?php
        endforeach;
    endif; ?>
    <div><?php print $page['form']; ?></div>
    <?php print $page['footer_scripts']; ?>
  </body>
</html>

これにより、必要に応じてログインページがカスタマイズされます。


2

@Sithu@Ayesh Kの両方が素晴らしい答えを提供してくれました。この例では、@ Ayeshのメソッドと@Sithuのコードの一部を組み合わせて完全なソリューションを作成します。

hooks_menuまたはhook_menu_alter関数はどちらもを提供しdelivery callback、コードをラップする方法をDrupalに指示します。デフォルトでは、Drupalはセットdelivery callbackdrupal_deliver_html_page()大まかにあなたのページをラップするためのDrupalを伝え、html.tpl.phpそしてpage.tpl.php

Drupalがページをラップする方法を変更するには、関数drupal_deliver_html_page()をモジュールにコピーして変更します。次に、新しい関数をで呼び出しますdelivery callback。Drupalはその関数を使用してページをラップします。

ここに作業モジュールがあります。次のコードを/sites/all/modules/MYMODULEディレクトリに配置し、モジュールを有効にします。

必要に応じて、既存のパス、代替上書きするhook_menuとしhook_menu_alter

MYMODULE.module

<?php
function MYMODULE_menu() {
  $items['login'] = array(
    'title' => 'Login',
    'page callback' => 'MYMODULE_page',
    'delivery callback' => 'MYMODULE_deliver',
    'access callback' => TRUE,
  );
  return $items;
}

function MYMODULE_page() {
  global $user;
  if (!$user->uid) return drupal_get_form('user_login'); // Show login for guests.
  else drupal_goto('user/' . $user->uid); // Redirect members to own profile.
}

// Code taken from drupal_deliver_html_page().
function MYMODULE_deliver($page_callback_result) {
  global $language, $base_path;
  // Pass variables to the template.
  $vars = array(
    'language' => $language->language,
    'title' => 'My Custom Login',
    'favicon' => '',
    'css' => $base_path . drupal_get_path('module', 'MYMODULE') . '/MYMODULE.css',
    'messages' => theme_status_messages(array('display' => NULL)),
    'content' => drupal_render($page_callback_result),
  );
  echo theme('MYMODULE_login', array('vars' => $vars)); // Uses template defined in hook_theme().
  drupal_page_footer();
}

function MYMODULE_theme() {
  $items['MYMODULE_login'] = array(
    'template' => 'MYMODULE',
    'render element' => 'page',
  );
  return $items;
}

MYMODULE.info

name = MYMODULE
description = "Module description."
package = Custom
core = 7.x

MYMODULE.tpl.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php print $vars['language']; ?>" version="XHTML+RDFa 1.0">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title><?php print $vars['title']; ?></title>
  <?php print $vars['favicon']; ?>
  <link rel="stylesheet" type="text/css" href="<?php print $vars['css']; ?>">
</head>
<body>
  <?php echo $vars['messages']; ?>
  <div class="content">
    <?php print $vars['content']; ?>
  </div>
</body>
</html>

MYMODULE.css

.content { color: pink; }

質問:この例はDrupalのキャッシングシステムで動作しますか。また、クエリ文字列ごとに個別のキャッシュがありますか?
Darvanen 2015年

デフォルトでは、Drupalはフォームとページをそれぞれキャッシュします。他のキャッシュプロセスについてはよくわかりません。
timofey.com、2015年

ありがとう。APIを使用してページ応答用のカスタムキャッシュを作成することになりました。
Darvanen 2015年

1

これに最も適したフックを見つけるために、時間をかける必要があると思います。あなたが試すことができます

  • hook_page_alterは「何がレンダリングされるか」を変更し、

  • hook_menu_alterを使用して、ログインの配信コールバックを変更し、メニュールーターを登録します。

  • page--user-login.tpl.phpファイル使用して、ログインページのページテンプレートを引き継ぎます。

  • ログインパスにのみ別のhtml.tpl.phpファイルを使用するために、template.phpにいくつかのテンプレート提案を追加します。

  • または、最後にhook_theme_regitry_alterを使用して、テーマレジストリを変更し、やりたいことを行います(html.tpl.phpの変更)。


+1スポットオン!hook_theme_registry_alter()すべてのページのテンプレートを変更する可能性が高いため、機能しない可能性がありますが、delivery callback確実に機能します。私はここで私の答えでこの方法をさらに調査しました。
timofey.com 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.