In my new 5.1 site, blocks are hidden when displaying a 404 page, this destroy the design of the page and make impossible to navigate (menus are in left block). Is there some place where we could configure this to show blocks in 404 and 403 pages???

Thanks.

Comments

catch’s picture

Block display was taken out of 5.x to avoid the performance hit of loading them on 404 pages.

You could make a node, then set this as your 404 page with the menu (or just a few links) in the body of the node (you could even include the block with a php snippet so it changes with your main navigation menu to save duplicating the structure.

Not sure how you'd go about setting blocks on the 404 page if you really want them back, but it'd probably involve modifying core.

leflores’s picture

Pages are really ugly without the left/right blocks, design is lost. I am using Garland and the logo is almost covered by the content (node) area... any way to avoid this???

Luis Flores
http://www.solutionsdepot.com

catch’s picture

If you're really bothered by it, and to avoid hacking core, you could add a redirect for your custom 404 page which redirects to a page of your choice. path_redirect might work for that. I'm not saying this is a great idea though.

There's also a 404 search module around which you could try out

cmsproducer’s picture

This is not a solution to the present problem, but something to be considered by the module designer for the next version of the module.

1) Throttle: What is you require throttle to be turned on by default for search-404, and throttle off all the blocks. If the owner of a given website has enough resources to handle the performance demand, then he/she can turn-on the blocks

2) Caching: You can set search-404 to require block caching or to only display cached blocks so that if the site admin wants blocks to show, then he/she must set those particular blocks to be cached. This will solve the theming issue without introducing the performance issue

-----
iDonny Productions: Drupal CMS Implementation, Theme UI/UX Design & Development, and Web Standards

butterfi’s picture

Inside the .htaccess file you can change:

# Customized error messages.
ErrorDocument 404 /index.php

to something like:
# Customized error messages.
ErrorDocument 404 /my_error_page.html

and then create your own error page.

(Tip o' the hat to Nate Haug for pointing this out to me)

kirie’s picture

I have a similar problem, where I've tried to explicitly set the error page like this:
ErrorDocument 404 /oops.html

The oops.html file is just a simple static HTML file in the root directory of Drupal (D5.3)

When I access something like http://www.example.com/asdasd I just get the same old Drupal 'page not found', not my custom 404 page. I've tried this on both Linux and Windows, with and without clean URL's.

Any idea what might be wrong?

mdlueck’s picture

Any idea what might be wrong?

I never found a way to get a non-Drupal 404 page with Drupal on the server.

We have and are doing several static HTML to Drupal conversions. While the Drupal site is under development, I comment out the default page in the .htaccess so that Drupal does not take over.

Also I have tried setting a static HTML page as the 404 page. However, a Drupal 404 page comes up, so I have quit trying and simply let Drupal handle it.

--
Michael Lueck
Lueck Data Systems
http://www.lueckdatasystems.com/

d.chatry’s picture

I tried but I couldn't find a way to redirect it to an internal Drupal node, so I'll let my little workaround here in case that could help anyone :

  • create a 404 page via "Create content > Page"
  • in your "drupal" (or root) folder, edit the "index.php" file
  • around line 20 there's a switch for each "not found/not allowed" case
  • instead of "drupal_not_found();" put "drupal_goto('node/xxxx')" (or the path to your 404 page)
  • save and enjoy

I know this is not the cleanest solution but meh, it works.

behindthepage’s picture

If you want to hack the core, all you need to do is change line 356 in common.inc (found in the includes folder)

From
  print theme('page', $return, FALSE);
To
  print theme('page', $return);

Easy!

gpdinoz
"Everything should be made as simple as possible, but not simpler." - Albert Einstein

Regards
Geoff

dvessel’s picture

No need to hack core. Just override theme_page function then call phptemplate_page right after from your template.php file.

Remember to rename "YOURTHEME_page" with the name of your theme.

<?php
function YOURTHEME_page($content, $show_blocks = TRUE) {

 
// Set additional conditions to change $show_blocks if you want here..
  // The following will always set $show_blocks to TRUE.
 
$show_blocks = $show_blocks ? $show_blocks : TRUE;

 
// phptemplate_page is what gets called usually but the
  // theme function allows us to override it with the themes' name.
  // We're calling it directly here so we don't have to copy tons of code.
 
return phptemplate_page($content, $show_blocks);
}
?>

To see why this works Look at this function. http://api.drupal.org/api/5/function/theme

If the only reason your trying to show the blocks is so it doesn't break your layout, then consider using the $layout var to set a body class. With some css knowledge it can be easily be fixed and you don't burden your sever with unnecessary load from rendering the sidebars.

joon park

BlakeLucchesi’s picture

This worked perfectly, thank you very much.

jabba_29’s picture

The theme_page override worked perfectly for me.

Regards

Jamie

skiFFie: home of the accessibility module?

Regards

Jamie

Mobile Movie Database

mdlueck’s picture

I just migrated one static HTML site to Drupal, so this makes the NUMEROUS 404's look like a normal pages! :-) :-) :-)

--
Michael Lueck
Lueck Data Systems
http://www.lueckdatasystems.com/

emackn’s picture

thanks, this works great.

jomtois’s picture

That little snippet worked great! Just cut and paste into template.php...

Cool!

davedelong’s picture

Not to be a troll or anything... but...

<?php
$show_blocks
= $show_blocks ? $show_blocks : TRUE;
?>

Can easily be replaced with:

<?php
$show_blocks
= TRUE;
?>
earnie’s picture

Just remove the code setting $show_blocks and pass TRUE to phptemplate_page.

<?php
phptemplate_page
($content, TRUE);
?>
Zoologico’s picture

This worked nicely.
Thanks.

Renzy’s picture

@ dvessel

I assume that the solution outlined here is only suitable if you always want your blocks to show up on every page (including the 404 one).

My situation is that I have a site where I use the left and right blocks (in gardland, fluid width 6.4) on some pages but not on others. So I am after a solution that allows me to say 'yes' show the blocks on the 404 page, but not interfere with the hiding of blocks on other parts of my site.

Can you let me know if this is do-able, not really keen to hack core either.

Thanks,
Renaee.

mdlueck’s picture

but not interfere with the hiding of blocks on other parts of my site.

You may still use the Admin \ Blocks interface to specify certain URL's to hide certain blocks. This trick does not override that.

--
Michael Lueck
Lueck Data Systems
http://www.lueckdatasystems.com/

Renzy’s picture

this did not make any change on my test site, I inserted the code within my template.php page (within my garland theme file).

Was there something else I missed? replaced yourtheme_page with garland.

Ta.
Renaee.

dvessel’s picture

That bit I posted won't work in 6. An alternative is to rename the side regions from the .info file. The 404 hiding behavior is specific to the region names "left" and "right". Naming it something else will bypass that behavior.

You also have to rename the region variables inside the page.tpl.php so it matches what you set inside .info. Garland also passes the region variables to a function that generates classes in the body tag. Make sure they match too.

You should do this on a copy of Garland or make a sub-theme from it.

As mdlueck mentions, it will not interfere with the block visibility settings but you will have to reassign the blocks to the newly named regions.

joon park
www.dvessel.com

joon park

Alan D.’s picture

This fails in Drupal 6 as there is no phptemplate_page. After doing a search and having no luck, I came up with the following solution to show the left and right regions.

<?php
/**
 * Override or insert PHPTemplate variables into the templates.
 */
function phptemplate_preprocess_page(&$vars) {
 
// handy helper for themes, not related to 404 issue
 
$vars['base_path'] = base_path();

 

// Only does the check if required
 
if(!$vars['show_blocks']) {
    global
$theme;
   
$regions = system_region_list($theme);
    foreach (
array_keys($regions) as $region) {
     
// Only set left and right regions
      // Drupal core sets the other blocks already
      // IMHO this shows a real lack of design considerations for leaving these out!
     
if ($region == 'left' || $region == 'right') {
       
$blocks = theme('blocks', $region);
        if(isset(
$variables[$region])) {
         
$vars[$region] .= $blocks;
        }
        else {
         
$vars[$region] = $blocks;
        }
      }
    }
  }
}
?>

Hope it helps.


Alan Davison
www.caignwebs.com.au
Renzy’s picture

I did not use your handy helper for themes section, just the bit that controls the 404 page.

So my code is as follows:

/**
* Override or insert PHPTemplate variables into the templates.
*/
function phptemplate_preprocess_page(&$vars) {
  $vars['tabs2'] = menu_secondary_local_tasks();
 
  // Hook into color.module
  if (module_exists('color')) {
    _color_page_alter($vars);
  }

// had to remove a closing brace here, but technically it should be there?

// Only does the check if required - see this node for explanation http://drupal.org/node/129762
  if(!$vars['show_blocks']) {
    global $theme;
    $regions = system_region_list($theme);
    foreach (array_keys($regions) as $region) {
      // Only set left and right regions
      // Drupal core sets the other blocks already
      // IMHO this shows a real lack of design considerations for leaving these out!
      if ($region == 'left' || $region == 'right') {
        $blocks = theme('blocks', $region);
        if(isset($variables[$region])) {
          $vars[$region] .= $blocks;
        }
        else {
          $vars[$region] = $blocks;
        }
      }
    }
  }
}

Once I removed the closing bracket (which php error notice emitted) the template with the fix was working. I don't quite understand why, I changed nothing else, and that extra curly brace should be there? Thanks if you can advise further.

Renaee.

Alan D.’s picture

You must have copied the last bit of the code segment and pasted this after the closing brace of the existing function phptemplate_preprocess_page. This would cause that error. I wouldn't worry, the code you pasted above looks perfect.


Alan Davison
www.caignwebs.com.au
scottrigby’s picture

Hi Alan,
This works to add the sidebars back in :)

But it doesn't change the body class (still has 'no-sidebars') -- so the info overlaps :(

I'm using a zen subtheme - based on the current version zen theme.

Any advice for this?

Cheers!
Scott

scottrigby’s picture

Ok, so I got it working for now. But there's probably a cleaner way to do this. I grabbed the function from zen/template.php, and here's what I added...

<?php
// account for search 404 pages
 
if ($section == 'search404') {
   
array_pop($body_classes); // Remove 'section-search404'
   
$body_classes[] = 'sidebar-left'; // Add sidebar on this page.
 
}
?>

...to my ZENSUBTHEME_preprocess_page function. This added a 'sidebar-left' class (which visually solved my problem). I also was able to remove extra 'section-search404' classes.

* The Problem is, I'm still getting duplicate 'page-search404' body classes (3 of 'em!). It's not the end of the worls, but it makes me feel like there's a cleaner way.

So in total my code looks like this now:

<?php
/**
 * Override or insert variables into the page templates.
 *
 * @param $vars
 *   An array of variables to pass to the theme template.
 * @param $hook
 *   The name of the template being rendered ("page" in this case.)
 */
function MYZENSUBTHEME_preprocess_page(&$vars, $hook) {
 
// Keep the line below, comment-out for now
  //$vars['sample_variable'] = t('Lorem ipsum.');
  // FROM drupal.org/node/129762#comment-1013470 (shows blocks even on 404 pages)
  // Only does the check if required
 
if(!$vars['show_blocks']) {
    global
$theme;
   
$regions = system_region_list($theme);
    foreach (
array_keys($regions) as $region) {
     
// Only set left and right regions
      // Drupal core sets the other blocks already
      // IMHO this shows a real lack of design considerations for leaving these out!
     
if ($region == 'left' || $region == 'right') {
       
$blocks = theme('blocks', $region);
        if(isset(
$variables[$region])) {
         
$vars[$region] .= $blocks;
        }
        else {
         
$vars[$region] = $blocks;
        }
      }
    }
  }
 
// Override from zen/template.php:
  // Classes for body element. Allows advanced theming based on context
  // (home page, node of certain type, etc.)
 
$body_classes = array($vars['body_classes']);
  if (!
$vars['is_front']) {
   
// Add unique classes for each page and website section
   
$path = drupal_get_path_alias($_GET['q']);
    list(
$section, ) = explode('/', $path, 2);
   
$body_classes[] = zen_id_safe('page-' . $path);
   
$body_classes[] = zen_id_safe('section-' . $section);
    if (
arg(0) == 'node') {
      if (
arg(1) == 'add') {
        if (
$section == 'node') {
         
array_pop($body_classes); // Remove 'section-node'
       
}
       
$body_classes[] = 'section-node-add'; // Add 'section-node-add'
     
}
      elseif (
is_numeric(arg(1)) && (arg(2) == 'edit' || arg(2) == 'delete')) {
        if (
$section == 'node') {
         
array_pop($body_classes); // Remove 'section-node'
       
}
       
$body_classes[] = 'section-node-' . arg(2); // Add 'section-node-edit' or 'section-node-delete'
     
}
    }
  }
  if (
theme_get_setting('zen_wireframes')) {
   
$body_classes[] = 'with-wireframes'; // Optionally add the wireframes style.
 
}
 
// account for search 404 pages
 
if ($section == 'search404') {
   
array_pop($body_classes); // Remove 'section-search404'
   
$body_classes[] = 'sidebar-left'; // Add sidebar on this page.
 
}
 
$vars['body_classes'] = implode(' ', $body_classes); // Concatenate with spaces
}
?>

Any advice for cleaning out those duplicate 'page-' body classes would be great.
Cheers :)
Scott

Apfel007’s picture

Hi Scott,
i tried your code.. why are no menus shown? arn't they blocks too - isn't it?

Cheers Apfel007

Alan D.’s picture

The block creation code done by Drupal is the first in the preprocess_page function chain. The theme is the last in this chain.

So if anything in between changes that is dependent on the regions, this will need to be mimicked here. As per the body class issue noted.


Alan Davison
www.caignwebs.com.au
Renzy’s picture

scratch that - works after all,
ta,
Renaee.

Alan D.’s picture

Just used the function for the first time using a theme that required the body classes, and the following modifications were needed to mimic the body classes. This is independent on the order of classes within the body_classes variable, as these could change without notice.

<?php
/**
* Override or insert PHPTemplate variables into the templates.
*/
function phptemplate_preprocess_page(&$vars) {
 
// Only does the check if required
 
if(!$vars['show_blocks']) {
    global
$theme;
   
$regions = system_region_list($theme);
    foreach (
array_keys($regions) as $region) {
      if (
$region == 'left' || $region == 'right') {
       
$blocks = theme('blocks', $region);
        if(isset(
$variables[$region])) {
         
$vars[$region] .= $blocks;
        }
        else {
         
$vars[$region] = $blocks;
        }
      }
    }
   
// redoing core classes
    // Set up layout variable.
   
$vars['layout'] = 'none';
    if (!empty(
$vars['left'])) {
     
$vars['layout'] = 'left';
    }
    if (!empty(
$vars['right'])) {
     
$vars['layout'] = ($vars['layout'] == 'left') ? 'both' : 'right';
    }
   
// redo body classes
   
$body_classes = explode(' ', $vars['body_classes']);
    foreach(
$body_classes as $index => $bc) {
      if (
$bc == 'no-sidebars') {
        unset(
$body_classes[$index]);
      }
    }
   
// Add information about the number of sidebars.
   
if ($vars['layout'] == 'both') {
     
$body_classes[] = 'two-sidebars';
    }
    elseif (
$vars['layout'] == 'none') {
     
$body_classes[] = 'no-sidebars';
    }
    else {
     
$body_classes[] = 'one-sidebar sidebar-'. $vars['layout'];
    }
   
// Implode with spaces.
   
$vars['body_classes'] = implode(' ', $body_classes);
  }
}
?>

Alan Davison
www.caignwebs.com.au
jonathan1055’s picture

Thanks AlanD for this. I have implemented it sucessfully. Just thought I would share a couple of changes I made:

1. There is a typo in the code above (and every other example copied from it on this page!) where if(isset($variables[$region])) should actually be if(isset($vars[$region])). I think you took this code originally from template_preprocess_page() in /includes/theme.inc where it is $variables, but in phptemplate_preprocess_page() and mytheme_preprocess_page() the variable is named $vars. I don't know why this is done like this, makes copying into your own function more tiresome!.

2. I used the code suggested previously to detect if we are on a 403 or 404 page and used this to ensure that the changes only affect the pages we are interested in. ie:

<?php
  $is403
= $_GET['q'] == drupal_get_normal_path(variable_get('site_403', ''));
 
$is404 = $_GET['q'] == drupal_get_normal_path(variable_get('site_404', ''));

 
// If we are on a 403 or 404 page then put the blocks back on.
 
if(!$vars['show_blocks'] && ($is403 || $is404)) {
    ...
?>

This may not strictly be necessary but I have not quite got my head around when else this code may be triggered, so I thought better to be safe.

Hope this helps anyone else implementing this change. Thanks again to all who have contributed here.

Jonathan

mdost@sharpdotinc.com’s picture

This got the blocks on the 404 page, but Blocks that are page specific are showing up. EX: a tag cloud block that should only show up on pages that have urls like "blog/*" are showing on the 404 page. Is there any way to remove these blocks? I would only want blocks that show on all pages.

Open Source Development - www.sharpdotinc.com

mdlueck’s picture

Greetings Alan-

I just realized that domains I upgraded to D6 were not displaying all blocks on 404 pages.

For D5 I had added code to template.php as suggested above on this thread.

Was your code intended to also go in template.php to show blocks on D6 404 pages, or in some other file? I am not receiving all blocks. I also tried the other solution, a customization of your solution, and that causes a PHP error.

Thanks!

--
Michael Lueck
Lueck Data Systems
http://www.lueckdatasystems.com/

Alan D.’s picture

The blocks 404 module is worth a go, either to:

a - see what has changed on the D6 code

or

b - simply to run the module rather than c'n'pasting the code into your template.

PS: The block coding stuff should be in the preprocess page theme hook

Sami_Ghname82’s picture

I put this code but not work.

i need to show header blocks in custom page not found

Alan D.’s picture

The blocks 404 module has a much nicer way of doing this now. Best check it out

hargobind’s picture

Here is a slightly better version of the code that dvessel posted in comment #27 above.

<?php
function YOURTHEME_page($content, $show_blocks = TRUE) {
 
// Set additional conditions to change $show_blocks if you want here...
 
$is404 = $_GET['q'] == drupal_get_normal_path(variable_get('site_404', ''));
 
$show_blocks = $is404 ? true : $show_blocks;
 
 
// phptemplate_page is what gets called usually but the
  // theme function allows us to override it with the themes' name.
  // We're calling it directly here so we don't have to copy tons of code.
 
return phptemplate_page($content, $show_blocks);
}
?>

The main difference is that we're only forcing blocks to display on a 404 page (where they are implicitly disabled). Otherwise, we're letting $show_blocks behave as normal.

The 404 path is set under Admin > Site configuration > Error Reporting in the "Default 404 (not found) page" field. This will still work even if that field is empty.

dvessel’s picture

That's a good idea. I'm not aware of any other pages where the block regions would not show but sometimes it's better to play it safe.

joon park
www.dvessel.com

joon park

bwv’s picture

This worked nicely, thank you.
----------------------------------------------------------------------
http://classicvinyl.biz
http://music.bwv810.com
http://davidhertzberg.com
http://association.drupal.org/user/1207

I am a writer, researcher and solo drupal freelancer

----------------------------------------------------------------------
http://classicvinyl.com

Alan D.’s picture

Continuing this on one step further:

<?php
function YOURTHEME_page($content, $show_blocks = TRUE) {
 
// Set additional conditions to change $show_blocks if you want here...
 
$is404 = $_GET['q'] == drupal_get_normal_path(variable_get('site_404', ''));
 
$is403 = $_GET['q'] == drupal_get_normal_path(variable_get('site_403', ''));
 
$show_blocks = ($is404 || $is403) ? true : $show_blocks;
 
// phptemplate_page is what gets called usually but the
  // theme function allows us to override it with the themes' name.
  // We're calling it directly here so we don't have to copy tons of code.
 
return phptemplate_page($content, $show_blocks);
}
?>

Alan Davison
www.caignwebs.com.au
alexkb’s picture

Thanks Alan and Linxor, this works perfectly in D5!

Sami_Ghname82’s picture

Hi all,

this code not work with me,

i used the drupal 6 when i put this code have this error.

Fatal error: Call to undefined function phptemplate_page() in /Users/samighname/Sites/elpis/htdocs/sites/all/themes/sky/template.php on line 40 ;

i search tow day about this solution but i can't find any thinks.

tingdongc’s picture

Sorry, but this is very misleading. Please don't provide such solutions. Drupal programmer should NEVER hack the core. Patch it or leave it.

There is the module blocks404 does the trick.

dregster’s picture

the quick edit in common.inc worked like a charm.

calypsorajesh’s picture

I never found a way to get a non-Drupal 404 page with Drupal on the server.

We have and are doing several static HTML to Drupal conversions. While the Drupal site is under development, I comment out the default page in the .htaccess so that Drupal does not take over.

Also I have tried setting a static HTML page as the 404 page. However, a Drupal 404 page comes up, so I have quit trying and simply let Drupal handle it

mdlueck’s picture

Same findings / solution here.

--
Michael Lueck
Lueck Data Systems
http://www.lueckdatasystems.com/

JohnAlbin’s picture

I just implemented a module-based solution to this problem. You can see the details of what it does at http://drupal.org/project/blocks404

  - John (JohnAlbin)

  - John (JohnAlbin)

chakrax’s picture

John - thank you very much - works well for me.

gluxon’s picture

It doesn't work for me :(

I tried both versions, cleared cache (My browser and the site) with no luck.

I even ran a cron and update.php.

I'm using Drupal 6.9 right now.

JohnAlbin’s picture

If you can't get it to work, submit a support request/bug report: http://drupal.org/project/issues/blocks404

  - John (JohnAlbin)

  - John (JohnAlbin)

Bilalx’s picture

Search 404 module has an option to show right and left regions.

To duplicate this behaviour:
In sites/all/modules/customerror/customerror.module
Line 170 replace

return $output

by

  print theme('page', $output);
  drupal_page_footer();
  unset($output);
  exit (0);
Lukas238’s picture

Excellent solution for CustomError Module.

It works great in Drupal 6 and CustomError 6.x-1.0.

Thanks Jaafarix!

roychri’s picture

This is no longer an issue in Drupal 7.
#423992: Remove show_blocks page variable

Blocks will not be hidden on page not found.

--
Drupal Freelancer (Module Developer)
Christian Roy

Alan D.’s picture

Wanting to keep the module count low in Drupal 6 site we are setting up, I discovered the following way to change the $show_blocks variable before any of the core system is triggered.

The code is from a module called "htsa"

<?php
/**
 * Implementation of hook_theme_registry_alter().
 *
 * This adds the new preprocess function onto the theme stack, but at the start
 * so it is called before the problematic template_preprocess_page() function.
 */
function htsa_theme_registry_alter(&$theme_registry) {
 
$path = drupal_get_path('module', 'htsa');
  if (isset(
$theme_registry['page']) && isset($theme_registry['page']['theme paths'])) {
   
array_unshift($theme_registry['page']['theme paths'], $path);
   
array_unshift($theme_registry['page']['preprocess functions'], 'htsa_pre_preprocess_page');
  }
}

/**
 * Toogle the block flag here :)
 */
function htsa_pre_preprocess_page(&$variables) {
 
// Set additional conditions to change $show_blocks if you want here...
 
$is404 = $_GET['q'] == drupal_get_normal_path(variable_get('site_404', ''));
 
$is403 = $_GET['q'] == drupal_get_normal_path(variable_get('site_403', ''));
  if (
$is404 || $is403) {
   
$breadcrumbs = array(l(t('Home'), ''), drupal_set_title());
   
drupal_set_breadcrumb($breadcrumbs);
  }
 
$variables['show_blocks'] = ($is404 || $is403) ? true : $variables['show_blocks'];
}
?>
tehkemo’s picture

is that we should keep things simple so, if you are interested to display all blocks even if "page not found" error occurs - try to use http://drupal.org/project/blocks404 which do the trick ;)

Apple isn't only well tasting and great looking fruit...

altrugon’s picture

Does anybody knows how to do this for Drupal 7?
Sorry I just saw the solution above.

-------------------------------------------------
take a look -> www.altrugon.com