I'm building a website with wordpress and a bought template. I added some functionality to the options/page creation. One can set a general meta description in the options and a meta description for each page while creating it.
Although I'm entirely new to PHP, I managed to add everything necessary to my code. It wasn't all that hard and it works just fine. My questions are: Am I doing it right? How can I optimize my solution? What are the downsides of my approach?
HTML (header.php):
<?php
// Defining a global variable
global $page_meta_description;
// Initializing the variable with the set value from the page
$page_meta_description= get_post_meta($post->ID, MTHEME . '_page_meta_description', true);
// Add meta tag if the variable isn't empty
if ( $page_meta_description != "" ) { ?>
<meta name="description" content="<?php echo $page_meta_description; ?>" />
<?php }
// Otherwise add globally set meta description
else if ( of_get_option('main_meta_description') ) { ?>
<meta name="description" content="<?php echo of_get_option('main_meta_description'); ?>" />
<?php }
// Set global meta keywords
if ( of_get_option('main_meta_keywords') ) { ?>
<meta name="keywords" content="<?php echo of_get_option('main_meta_keywords'); ?>" />
<?php } ?>
You can use the wp_head hook.
// write this in your plugin
add_action('wp_head', 'myplugin_get_meta_tags');
function myplugin_get_meta_tags()
{
$content = '';
$content .= '<!-- add meta tags here -->';
return $content;
}
I think this is slightly more elegant that doing all the logic in the header.php file.
If you don't want to create a plugin for this, or it's needed for a single theme, you can add this code in the functions.php file in your theme (check the link for more info).
Note
The downside(s) to your solution are:
If you ever need to create a new template that uses a different header, you need to copy the meta code to each new file, and when you make changes, make them in all header files
The template files should have as little logic in them as possible, and having a bunch of ifs would clutter it unnecessarily.
Related
Currently I'm trying to filter out various things for the meta portion of my WordPress website, and I've found an issue, using the following code was working perfectly until I needed to get a bit more specific.
if (is_singular('post')) {
$title = get_the_title ();
print '<title>'.$title.'</title>';
$feat_image = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
print '<meta property="og:image" content="'.$feat_image.'"/>';
print '<meta name="description" content="" />';
} else {
print '<title></title>';
print '<meta name="description" content="" />';
}
Note that I edited the meta descriptions above so that they're empty, just for the sake of posting on stack.
Then I wanted to start filtering based on the tags a post has, and obviously this is going to conflict with the already declared (is_singular('post')) function above.
However, I used the code below.
if ( has_tag( 'spanish' )) {
print '<title>'.$title.'</title>';
$feat_image = wp_get_attachment_url( get_post_thumbnail_id($post->ID) );
print '<meta property="og:image" content="'.$feat_image.'"/>';
print '<meta name="description" content="" />';
}
And it is displaying the meta for this portion also in the category we wish for it too, how ever it's also displaying the meta description for the other function as well, what can I do stack?
This might sound simplistic, but firstly you want to document exactly what you want to happen. Maybe make yourself a flow chart or write a couple of paragraphs. Either way, you need to know from a non-code point of view first. This will enable you to answer questions like "Does a tag take precedence over a single post?" Once you know this process, move your conditions away from output to simplify the process. Something like this:
// defaults
$title = '...';
$metaDescription = '...';
$featuredImage = '...';
// overrides for difference scenarios
if (is_singular('post')) {
// set title, etc here
}
if (has_tag('spanish')) {
// override or concatenate title, etc here
}
// output
print "<title>$title</title>";
<!-- etc etc -->
This question already has answers here:
How to dynamically change a web page's title?
(20 answers)
Closed 8 years ago.
I would like to change the title of the HTML page based on the content, but im including only the content below the header part, so i have to change the title from this included php. To explain:
<html>
<header><title>I would like to change</title></header>
<!--CONTENT-->
<?
include "pages/some_page.php";
?>
</html>
How could i do that? Anyone can help in this?
You cant do that without a nasty hack.
What you should do is perform all your logic BEFORE you output html. A simple example follows:
<?php
//index.php
//perform logic and set variables before any html
$page = isset($_GET['menu'])?$_GET['menu']:'home';
switch($page){
case 'home':
$title = ' welcome to myco.ltd';
$content = 'pages/home.php';
break;
case 'about':
$title = 'about us';
$content = 'pages/about.php';
break;
case 'contact':
$title = 'get in touch';
$content = 'pages/contact.php';
break;
}
//the following html could be in a separate file and included, eg layout.php
?>
<html>
<head>
<title><?php echo $title;?></title>
</head>
<body>
<!--menu and other shared html here-->
<?php include $content;?>
<!-- shared footer stuff here-->
</body>
</html>
This is essentially a VERY barebones router script, an essential component of any framework. I would highly recommend you consider a lightweight framework rather than write everything from scratch. http://fatfreeframework.com/home would be a great start
The function below will let you change document title, meta keywords and meta description. You may use it anywhere in your application.
Just be sure to turn on output buffering using ob_start() before the function is called. I prefer including it at the top of application, just after all global settings are loaded.
function change_meta_tags($title, $keywords, $description){
$output = ob_get_contents();
if (ob_get_length() > 0) { ob_end_clean(); }
$patterns = array("/<title>(.*?)<\/title>/", "/<meta name=\"keywords\" content=\"(.*?)\" \/>/", "/<meta name=\"description\" content=\"(.*?)\" \/>/");
$replacements = array("<title>$title</title>", "<meta name=\"keywords\" content=\"$keywords\" />", "<meta name=\"description\" content=\"$description\" />");
$output = preg_replace($patterns, $replacements, $output);
echo $output;
}
Use javascript in some_page.php .
<?php echo "<script>document.title = '".$dynamicTitleVariable."';</script>"; ?>
Pending what you are trying to base the content off of, this could easily be done via an MVC-style setup. In your controller, you would generate the title based off of content that could be grabbed and pass this through to the view as a variable. Then, in your view have the title be dynamically set:
<html>
<head>
<title>
<?php echo $title; ?>
</title>
</head>
</html>
This should also work fine with SEO capability, as crawlers will be able to interpret this far better than they would JavaScript.
I'm currently using a conditional meta tag code in wordpress.
Everything is working fine, besides on certain pages.
code in header.php:
<meta name="description" content="<?php echo metadesc($post->ID); ?>" />
<?php }else{ ?>
<meta name="description" content="<?php bloginfo('description'); ?>" />
<?php } ?>
code in functions.php:
function metadesc($pid) {
$p = get_post($pid);
$description = strip_tags($p->post_content);
$description = str_replace ("\n","",$description);
$description = str_replace ("\r","",$description);
if (strlen($description) > 135) {
return htmlspecialchars(substr($description,0,135) . "...");
}else{
return htmlspecialchars($description);
}
}
This is what it shows when I go to the source and look at the meta tag description on the following pages:
home: (description of the home page that is defined in Wordpress general settings (check)
biography: first 135 characters of the page (check)
contact:
<meta name="description" content="[contact-form-7 id="25" title="Contact"]" />
As you can see, I only have a contact form on my contact page and it looks like I need to add a filter to the script so that it ignores script tags and short codes, and that it will place the homepage description instead.
How can I fix this issue?
What if you use the strip_shortcode function try this one
function metadesc($pid) {
$p = get_post($pid);
$description = strip_tags($p->post_content);
$description = str_replace ("\n","",$description);
$description = str_replace ("\r","",$description);
$description =strip_shortcodes($description );
if(empty($description )){
return please get home page content
}
else{
if (strlen($description) > 135) {
return htmlspecialchars(substr($description,0,135) . "...");
}else{
return htmlspecialchars($description);
}
}
}
strip_shortcodes
You're jumping in and out of PHP too often, which leads to coding mistakes and slow execution. Rewrite your first code:
<?php
echo '<meta name="description" content="' .
((some condition)? metadesc($post->ID): bloginfo('description')) . '" />';
?>
Now, if your raw data for the content is [contact-form-7 id="25" title="Contact"] what are you trying to turn this into? How would you like to see it reformatted? This is coming from the metadesc() function? I don't think that HTML entities in a description tag are going to be expanded to their characters, but will be used as-is. So, you might need to output [contact-form-7 id=\"25\" title=\"Contact\"] instead. Regardless, that's a very poor description -- what do you really want there?
Also be aware of whether you're in UTF-8 or a single byte encoding such as Latin-1, which becomes important when using substr() (you don't want to chop in the middle of a multibyte UTF-8 character). Also, if you're adding an ellipsis (...), you would want to take 132 characters and not 135.
I did something similar to this, conditionally taking the excerpt and using it as the description if the viewer is on a single post page & there is an excerpt. Here's the code:
<?php
if (is_single() && $post->post_excerpt != “”) {
$post = $wp_query->post;
$descrip = strip_tags($post->post_excerpt);
echo ‘<meta name=”description” content=”‘.$descrip.’”>’;
}
?>
I also wrote a blog post detailing the whole thing.
So I decided to give codeigniter a chance and convert my existing site which is all custom php to the codeigniter framework. But trying to figure out how to do this best in codeigniter that I was doing from my original site. In the original site a person would visit a page such as index.php. In the index.php code its broken into sections like so (This is just a very simple example):
index.php:
<html>
<head></head>
<body>
<div id="top">{$SECTION1}</div>
<div id="main">{$SECTION2}</div>
<div id="bottom">{$SECTION3}</div>
</body>
</html>
Then in my main php file that is included in every single page I run a query that grabs all "modules" that are assigned to each section above for the index.php page. So give me all modules that are assigned to {$SECTION1}, {$SECTION2} and {$SECTION3} for index.php. A module in my original system is simply a php file that does a specific job so I might have a module called latest_story.php and in the script it gets the last 10 stories from the database and display the results.
latest_story.php
include('class/story/story_class.php');
$story = new Story($databaseconn);
$latest_story = $story->findLatestStory(10);
//If results back from $latest_story loop through it
//and display it however I want
Then using output buffering I execute each module then take the outputted information from each module assigned to each section and replace that section with the outputted data.
Can this be done in codeigniter? If so can someone point me in the right direction in doing this in codeigniter?
EDIT
To give a more clear view of what Im doing in the original system I run a query on every single page to determine what "modules" to grab for the current page the person is viewing then run this code
foreach($page_modules AS $curr_module)
{
$module_section = intval($curr_module->section);
$module_file = $global_function->cleanData($curr_module->modfile);
$module_path = MODS .$module_file;
if(is_file($module_path))
{
ob_start();
include($module_path);
${'global_pagemod' .$module_section} .= ob_get_contents();
ob_end_clean();
}
}
Then I simply take each variable created for each section and replace {$SECTION[n]} with that variable in the template.
ADDITIONAL EDIT
What Im trying to do is be able to create "modules" that do specific tasks and then in the backend be able to dynamically place these modules in different sections throughout the site. I guess you can say its like wordpress, but a more simplier approach. Wordpress you can add a module and then assign it to your pages either in the left column, middle or right column. Im trying to do pretty much the same thing.
Basically, Codeigniter is an MVC framework. To use it, you really want to embrace that rather than include files. You can rejig your code as:
In your controller:
function example()
{
$this->load->model('story_model','story');
$data['section1'] = $this->story->latest();
$data['section2'] = $this->story->top_stories(5);
$data['section3'] = $this->story->most_popular();
$this->load->view('example', $data );
}
In your model:
function latest()
{
return $this->db->limit(1)->get('stories');
}
etc.
In your view:
<html>
....
<div id="latest">
<h2><?php echo $section1->title; ?></h2>
<?php echo $section1->body; ?>
</div>
<div id="top">
<?php foreach $section2 as $popular { ?>
<h2><?php echo $popular->title; ?></h2>
<?php echo $popular->body; ?>
<?php foreach} ?>
</div>
</html>
If you wanted a second page, with different content but the same layout, you'd add this to your controller:
function second_page()
{
$this->load->model('tags_model','tag');
$this->load->model('authors_model','author');
$data['section1'] = $this->tag->latest();
$data['section2'] = $this->tag->top_tags(5);
$data['section3'] = $this->author->most_popular();
$this->load->view('example', $data );
}
and add in new models etc.
You can pass the retrieved data as an array to the main view and then access that data on the subviews.
For example:
Main View
$posts = $this->post_model->fetch_all();
$top_data = $this->more_data_model->fetch_more_data();
$data = array('posts'=>$posts,'top_data'=>$top_data);
$this->load->view('main_view',$data);
Then on the main view you load the subviews:
$data = array('data_name'=>$top_data);
$this->load->view('top_view',$data);
And then on the subview you just use the data however you want. There might be a more effective way to do this, but i believe this'll do the trick. :)
I do it like this:
Controller:
function about()
{
$user_session = $this->model_user_lite->Session_Check();
$data['auth'] = $user_session;
$user_id = $this->model_user_lite->Session_UserID();
$data['user_id'] = $user_id;
$this->load->view( 'main_about.php', $data );
}
View:
<? $this->load->view('header_base.php'); ?>
<? $this->load->view('include_standart.php'); ?>
<? $this->load->view('header_standart.php'); ?>
<div class="box">
<div class="box-top"></div>
<div class="box-center">
<div class="content">
<center>
<h2><?= lang('MAIN_ABOUT_CAPTION_TEAM'); ?></h2>
<div class="hr"></div>
...
Header Base:
<!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">
<link rel="shortcut icon" href="<?= base_url(); ?>/favicon.ico" type="image/x-icon">
<link rel="icon" href="<?= base_url(); ?>/favicon_animated.ico" type="image/x-icon">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta property="fb:admin_id" content="677920913" />
<meta property="fb:app_id" content="<?= FACEBOOK_APPID; ?>" />
<meta property="og:site_name" content="<?= SITE_NAME; ?>" />
<?php if ( empty( $og_title ) === FALSE ): ?>
<meta property="og:title" content="<?= $og_title; ?>" />
<?php endif ?>
...
This way you have a clean file system, seperate header, you can even have more headers just as you like, and can assign all the data from the controller to the view.
**Variables that are assigned from the controller, also go to views loaded by your "main view".
I'm using it in a major dating website and it works like a charm.
I have seen the following thread but it's a bit beyond me...
How can I change the <title> tag dynamically in php based on the URL values
Basically, I have a page index.php (no php in it just named to future proof - maybe now!). It contains numerous lightbox style galleries which can be triggered from an external link by a variable in the URL - e.g. index.php?open=true2, index.php?open=true3, etc.
I would like the index.php title tag - to include existing static data + append additional words based on the URL variable - e.g. if URL open=true2 add "car gallery", if URL open=true3 add "cat gallery", if URL has no variable append nothing to title.
Can anyone assist? I have been searching but either missed the point of posts or it hasn't been covered (to my amateaur level).
Many thanks. Paul.
At the top of your php script put this:
<?php
# define your titles
$titles = array('true2' => 'Car Gallery', 'true3' => 'Cat Gallery');
# if the 'open' var is set then get the appropriate title from the $titles array
# otherwise set to empty string.
$title = (isset($_GET['open']) ? ' - '.$titles[$_GET['open']] : '');
?>
And then use this to include your custom title:
<title>Pauls Great Site<?php echo htmlentities($title); ?></title>
<title>Your Static Stuff <?php echo $your_dyamic_stuff;?></title>
<?php
if( array_key_exists('open', $_GET) ){
$title = $_GET['open'];
}else{
$title = '';
}
?>
<html>
<head>
<title><?php echo $title; ?></title>
</head>
<body>
The content of the document......
</body>
</html>
http://www.w3schools.com/TAGS/tag_title.asp
http://php.net/manual/en/reserved.variables.get.php
PHP can fetch information from the URL querystring (www.yoursite.com?page=1&cat=dog etc). You need to fetch that information, make sure it's not malicious, and then you could insert it into the title. Here's a simple example - for your application, make sure you sanitise the data and check it isn't malicious:
<?php
$open = "";
// check querystring exists
if (isset($_GET['open'])) {
// if it does, assign it to variable
$open = $_GET['open'];
}
?>
<html><head><title>This is the title: <?php $open ?></title></head>
PHP has lots of functions for escaping data that might contain nasty stuff - if you look up htmlspecialchars and htmlentities you should find information that will help.
Some of the other answers are open to abuse try this instead:
<?php
if(array_key_exists('open', $_GET)){
$title = $_GET['open'];
} else {
$title = '';
}
$title = strip_tags($title);
?>
<html>
<head>
<title><?php echo htmlentities($title); ?></title>
</head>
<body>
<p>The content of the document......</p>
</body>
</html>
Otherwise as #Ben has mentioned. Define you titles in your PHP first to prevent people from being able to directly inject text into your HTML.