Block visible for Specific Content Type AND Specific URL
Site administrators · Site users · Themers · Drupal 5.x · Drupal 6.x · Drupal 7.x · No known problems
Last modified: June 29, 2009 - 21:05
I wanted to have a block displayed for a specific content type but also displayed on a number of pages.
The solution is to create a single Block and choose PHP for visibility settings.
The PHP code goes as follows:
<?php
$match = FALSE;
$types = array('content-petites_annonces' => 1);
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($types[$type])) {
$match = TRUE;
}
}
if (substr($_SERVER["REQUEST_URI"], 0, 10) == '/petitesan')
{ $match = TRUE;}
if (substr($_SERVER["REQUEST_URI"], 0) == "/node/add/content-petites_annonces
")
{ $match = TRUE;}
return $match;
?>Basically the first part put $match to TRUE if the page is of the content type I want. The other 2 if statements are selection based on the URL of the page allowing me to activate the Block for the URL I want.
Note that Drupal 7 will reintroduce a GUI for block visibility by content type, which reduces dependency on snippets like this one.

Block visibility for node type and URL selection
Here's a more concise example which shows the block only on pages of specific node type and on the taxonomy pages. Tested on Drupal 5.x. Note the use of node_load argument and the arg() function for URL selection.
<?php
$match = FALSE;
$types = array('product' => 1);
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$match = isset($types[$node->type]);
}
$match |= ((arg(0) == 'taxonomy') && (arg(1) == 'term'));
return $match;
?>
Nice example. I adapted it
Nice example. I adapted it to show a block where either the URI is "/foo" or "/bar" or the node is of type "project". In the interest of platform independence, I used the request_uri() function.
If you needed to match a wildcard, this could be adapted by adding one of the regular expression functions.
<?php
$match = FALSE;
$types = array('project' => 1);
$uris = array('/foo' => 1, '/bar' => 1);
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$match = isset($types[$node->type]);
}
$match |= isset($uris[request_uri()]);
return $match;
?>
Hide block on node edit page
Here is an example for hiding a block on a node's edit page.
<?php
$match = TRUE;
$url = request_uri();
if (strpos($url, "edit")) {
$match = FALSE;
}
return $match;
?>
Block visibility on other pages can be controlled by adding additional if statements. This example hides block on "/admin/*", "/filter/tips", "/node/add", and "node/10" pages.
<?php
$match = TRUE;
$url = request_uri();
if (strpos($url, "admin")) {
$match = FALSE;
}
if (strpos($url, "filter/tips")) {
$match = FALSE;
}
if (strpos($url, "node/add")) {
$match = FALSE;
}
if (strpos($url, "edit")) {
$match = FALSE;
}
if (strpos($url, "node/10")) {
$match = FALSE;
}
return $match;
?>
I'm sure the code could be more efficient but would take away from showing the concept.
HTH,
Doug
Thanks for the snippet! I
Thanks for the snippet! I had searched for a while trying to figure out how to handle php block visibility to show on a list of specific pages and also page(s) with multiple conditions, like url=FOO and user_is_logged_in. This snippet helped me do it.
Here is my modified snipped that resolved my particular needs:
<?php
$url = request_uri();
$show_pages = array('account','library','search','myaccount','myaccount',);
foreach ($show_pages as $vis_page) {
if (strpos($url, $vis_page)) {return TRUE;}
}
// Multi-condition visibility
if (strpos($url, "user") && user_is_logged_in()) {
$match = TRUE;
}
return FALSE;
?>
Complete Computer Care
Block visible for Specific Content Type AND Specific URL
URLs to show block are in $path variable. It is possible to use '*' in URL.
Node types are in $types variable.
Block will show on one of URLs from $paths variable or where type of node is one from $types variable.
<?php
$paths = "forum\r\nforum/*\r\nuser\r\nuser/*\r\nadmin\r\nadmin/*";
$types = array('forum' => 1);
$match = FALSE;
$path = drupal_get_path_alias($_GET['q']);
$regexp = '/^('. preg_replace(array('/(\r\n?|\n)/', '/\\\\\*/', '/(^|\|)\\\\<front\\\\>($|\|)/'), array('|', '.*', '\1'. preg_quote(variable_get('site_frontpage', 'node'), '/') .'\2'), preg_quote($paths, '/')) .')$/';
if (preg_match($regexp, $path)) {
$match = TRUE;
}
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($types[$type])) {
$match = TRUE;
}
}
return $match;
?>
Another way to do it
I wanted a template function to identify types of content so users know whether they're editing a page, blog, image, etc.
I'm not an elegant coder, but the following worked for me,
function Sp0xx_is_ID($nid) {$page = array('page' => 1);
$story = array('story' => 1);
$image = array('image' => 1);
$blog = array('blog' => 1);
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($page[$type])) {
$output .= 'This is a Page.';
}
if (isset($story[$type])) {
$output .= 'This is a Story.';
}
if (isset($image[$type])) {
$output .= 'This is an Image.';
}
if (isset($blog[$type])) {
$output .= 'This is a Blog.';
}
}
return $output;
}
[[[ ALL HAIL THE ALMIGHTY GOOGLEBOT ]]]
content type + url with wildcard
Here's how my hacker husband adapted the script to accommodate a content type ("photo") and a url with a wildcard (/photos/*):
<?php
$match = FALSE;
$types = array('photo' => 1);
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$match = isset($types[$node->type]);
}
$match |= (ereg('/photos(/.*)?', request_uri()) != 0);
return $match;
?>
The opposite snippet
If you want a snippet that shows blocks on specific content types but hides the block on specific URLs, then follow up on that specific page. Here: http://drupal.org/node/502480
Specific URL code above didn't work for me but this change did.
I was unable to get the above code to work completely. Showing per content type worked fine but the addition of the specific URL did not work. I tried this on two different websites using Drupal 6 with no success. I'm not a programmer, but after looking at some of the other snippets provided I was able to get it to work correctly using the below snippet. Adding the $url variable at the top and changing the if statement. I'm not sure why I wasn't able to get the original code to work but so far my site hasn't crashed using this, all seems to be working fine.
<?php
$match = FALSE;
$url = request_uri();
$types = array('YOURNODETYPE' => 1);
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($types[$type])) {
$match = TRUE;
}
}
if (strpos($url, "YOUR/URL")) {
$match = TRUE;
}
return $match;
?>
-D
Perfect, thanks.
This snippet works perfect, thank you for adding it.
-= Jay August =-
Freelance Web Designer, Drupal Fanboy and WordPress Expert
Where do you place this code?
Would you place this code in the block body? Sorry im a newb!
------------------------------------------
Alvin Crespo
Interactive Developer and Designer
In your Block configuration
In your Block configuration under "Page specific visibility settings":
Select "Show if the following PHP code returns TRUE (PHP-mode, experts only)." and enter the PHP code in the box below it.
Complete Computer Care
the easiest way to get the type of content
<?php
// Change the type to the one you want to match on
$desired_type = 'story';
if ( arg(0) == 'node' && is_numeric(arg(1)) ) {
$node = node_load(arg(1));
return $node->type == $desired_type;
}
return FALSE;
?>
Subjective
If one doesn't speak PHP, and this snippet doesn't give examples for getting multiple content types, then things are still quite hard. How can this be customized to get multiple content types?
Thank you
That worked for me!
This worked for me.
None of the other options worked (but I'm a PHP newb) and so this simple option worked best. Now I just need a way to select a group of Pages and turn them to a content type to make more use of this. Wonderful. Thanks!
show block on all pages except for Front page and specific type
Hey
Your code for specific type visibility works.
I assume it works for the specific paths too (i havent tested).
But how do i refer to the front page on these snippets? I understand "front" isnt valid when you use Php.
What I want to do is show a certain block on All pages, except for Front page and a Specific type.
This does it :)
The following code works to show a block on all pages except on front page or a specific content type.
In this example the content type is called "sponsor".
<?php
$match = TRUE;
$types = array('sponsor' => 1);
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($types[$type])) {
$match = FALSE;
}
}
if (drupal_is_front_page()) {
$match = FALSE;
}
return $match;
?>
Do Not Show Block on Content Type X, Y and Z
In some cases it seems a lot more convenient to now show a block for a specific content type. For example, say I want to pull the Primary Links off of a certain section.
Anyone know how to adapt the above code to serve this purpose? Thanks.
______________________________________________________
Follow me at http://www.twitter.com/WebsterJ
The code directly above does
The code directly above does this
$types = array('sponsor' => 1);"Sponsor" is a content type. You can simply add your list of content types to this line to show the block for those types. Of course, you will have to modify the rest of the code to suite your needs as well.
Complete Computer Care
Adapted it a bit...
Great piece of code. Had issue with URL part though so I adapted it a bit. Also hated to keep writing the if statement for every page so I added an array and then a foreach.
Mine looks like this:
<?php
$match = FALSE;
$url = request_uri();
$types = array('NODE-TYPE' => 1);
$pages = array('URL1', 'URL2', 'URL3');
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($types[$type])) {
$match = TRUE;
}
}
foreach($pages as $page){
if (strpos($url, $page)) {
$match = TRUE;
}
}
return $match;
?>
Cheers,
Jason
how about frontpage?
tried both "frontpage" and "/" as URL1, but it doesn't work for me... Any suggestion? Thank you.
how to handle frontpage
I use path and pathauto for all my sites and for various reasons, or just old habits, I name my frontpage index.
But, that may not be something that you need or want to do. If that is the case, Drupal has a great function called drupal_is_front_page().
I modified the code to account for that.
<?php$front_page = drupal_is_front_page();
$match = FALSE;
$url = request_uri();
$types = array('NODE-TYPE' => 1);
$pages = array('URL1', 'URL2', 'URL3');
if($front_page){
$match = TRUE;
}
if (arg(0) == 'node' && is_numeric(arg(1))) {
$nid = arg(1);
$node = node_load(array('nid' => $nid));
$type = $node->type;
if (isset($types[$type])) {
$match = TRUE;
}
}
foreach($pages as $page){
if (strpos($url, $page)) {
$match = TRUE;
}
}
return $match;
?>
Cheers,
Jason