TOPIC: PHP
Add Canonical Tags to WordPress without plugins
31st March 2025Search engines need to know which is which because they cannot know which is the real content when there is any duplication, unless you tell them. That is where canonical tags come in handy. By default, WordPress appears to add these for posts and pages, which makes sense. However, you can add them for other places too. While a plugin can do this for you, adding some code to your theme's functions.php file also does the job. This is how it could look:
function add_canonical_link() {
global $post;
// Check if we're on a single post/page
if (is_singular()) {
$canonical_url = get_permalink($post->ID);
}
// For the homepage
elseif (is_home() || is_front_page()) {
$canonical_url = home_url('/');
}
// For category archives
elseif (is_category()) {
$canonical_url = get_category_link(get_query_var('cat'));
}
// For tag archives
elseif (is_tag()) {
$canonical_url = get_tag_link(get_query_var('tag_id'));
}
// For other archive pages
elseif (is_archive()) {
$canonical_url = get_permalink();
}
// Fallback for other pages
else {
$canonical_url = get_permalink();
}
// Output the canonical link
echo '' . "\n";
}
// Hook the function to wp_head
add_action('wp_head', 'add_canonical_link');
// Remove default canonical link
remove_action('wp_head', 'rel_canonical');
The first part defines a function to define the canonical URL and create the tag to be added. With that completed, the penultimate piece of code hooks it into the wp_head
part of the web page, while the last function gets rid of the default link to get avoid any duplication of output.
Rendering Markdown into HTML using PHP
3rd December 2022One of the good things about using virtual private servers for hosting websites instead of shared hosting or using a web application service like WordPress.com or Tumblr is that you get added control and flexibility. There was a time when HTML, CSS and client-side scripting were all that was available from the shared hosting providers that I was using back then. Then, static websites were my lot until it became possible to use Perl server side scripting. PHP predominates now, but Python or Ruby cannot be discounted either.
Being able to install whatever you want is a bonus as well, though it means that you also are responsible for the security of the containers that you use. There will be infrastructure security, but that of your own machine will be your own concern. Added power always means added responsibility, as many might say.
The reason that these thought emerge here is that getting PHP to render Markdown as HTML needs the installation of Composer. Without that, you cannot use the CommonMark package to do the required back-work. All the command that you see here will work on Ubuntu 22.04. First, you need to download Composer and executing the following command will accomplish this:
curl https://getcomposer.org/installer -o /tmp/composer-setup.php
Before the installation, it does no harm to ensure that all is well with the script before proceeding. That means that capturing the signature for the script using the following command is wise:
HASH=`curl https://composer.github.io/installer.sig`
Once you have the script signature, then you can check its integrity using this command:
php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') === '$HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
The result that you want is "Installer verified". If not, you have some investigating to do. Otherwise, just execute the installation command:
sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
With Composer installed, the next step is to run the following command in the area where your web server expects files to be stored. That is important when calling the package in a PHP script.
composer require league/commonmark
Then, you can use it in a PHP script like so:
define("ROOT_LOC",$_SERVER['DOCUMENT_ROOT']);
include ROOT_LOC . '/vendor/autoload.php';
use League\CommonMark\CommonMarkConverter;
$converter = new CommonMarkConverter();
echo $converter->convertToHtml(file_get_contents(ROOT_LOC . '<location of markdown file>));
The first line finds the absolute location of your web server file directory before using it when defining the locations of the autoload script and the required markdown file. The third line then calls in the CommonMark package, while the fourth sets up a new object for the desired transformation. The last line converts the input to HTML and outputs the result.
If you need to render the output of more than one Markdown file, then repeating the last line from the preceding block with a different file location is all you need to do. The CommonMark object persists and can be used like a variable without needing the reinitialisation to be repeated every time.
The idea of building a website using PHP to render Markdown has come to mind, but I will leave it at custom web pages for now. If an opportunity comes, then I can examine the idea again. Before, I had to edit HTML, but Markdown is friendlier to edit, so that is a small advance for now.
Moving a website from shared hosting to a virtual private server
24th November 2018This year has seen some optimisation being applied to my web presences, guided by the results of GTMetrix scans. It was then that I realised how slow things were, so server loads were reduced. Anything that slowed response times, such as WordPress plugins, got removed. Usage of Matomo also was curtailed in favour of Google Analytics, while HTML, CSS and JS minification followed. Something that had yet to happen was a search for a faster server. Now, another website has been moved onto a virtual private server (VPS) to see how that would go.
Speed was not the only consideration, since security was a factor too. After all, a VPS is more locked away from other users than a folder on a shared server. There also is the added sense of control, so Let's Encrypt SSL certificates can be added using the Electronic Frontier Foundation's Certbot. That avoids the expense of using an SSL certificate provided through my shared hosting provider, and a successful transition for my travel website may mean that this one undergoes the same move.
For the VPS, I chose Ubuntu 18.04 as its operating system, and it came with the LAMP stack already in place. Have offload development websites, the mix of Apache, MySQL and PHP is more familiar to me than anything using Nginx or Python. It also means that .htaccess
files become more useful than they were on my previous Nginx-based platform. Having full access to the operating system using SSH helps too and should mean that I have fewer calls on technical support since I can do more for myself. Any extra tinkering should not affect others either, since this type of setup is well known to me and having an offline counterpart means that anything riskier is tried there beforehand.
Naturally, there were niggles to overcome with the move. The first to fix was to make the MySQL instance accept calls from outside the server so that I could migrate data there from elsewhere, and I even got my shared hosting setup to start using the new database to see what performance boost it might give. To make all this happen, I first found the location of the relevant my.cnf
configuration file using the following command:
find / -name my.cnf
Once I had the right file, I commented out the following line that it contained and restarted the database service afterwards, using another command to stop the appearance of any error 111 messages:
bind-address 127.0.0.1
service mysql restart
After that, things worked as required and I moved onto another matter: uploading the requisite files. That meant installing an FTP server, so I chose proftpd since I knew that well from previous tinkering. Once that was in place, file transfer commenced.
When that was done, I could do some testing to see if I had an active web server that loaded the website. Along the way, I also instated some Apache modules like mod-rewrite using the a2enmod
command, restarting Apache each time I enabled another module.
Then, I discovered that Textpattern needed php-7.2-xml installed, so the following command was executed to do this:
apt install php7.2-xml
Then, the following line was uncommented in the correct php.ini configuration file that I found using the same method as that described already for the my.cnf
configuration and that was followed by yet another Apache restart:
extension=php_xmlrpc.dll
Addressing the above issues yielded enough success for me to change the IP address in my Cloudflare dashboard so it pointed at the VPS and not the shared server. The changeover happened seamlessly without having to await DNS updates as once would have been the case. It had the added advantage of making both WordPress and Textpattern work fully.
With everything working to my satisfaction, I then followed the instructions on Certbot to set up my new Let's Encrypt SSL certificate. Aside from a tweak to a configuration file and another Apache restart, the process was more automated than I had expected, so I was ready to embark on some fine-tuning to embed the new security arrangements. That meant updating .htaccess
files and Textpattern has its own, so the following addition was needed there:
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
This complemented what was already in the main .htaccess
file, and WordPress allows you to include http(s) in the address it uses, so that was another task completed. The general .htaccess
only needed the following lines to be added:
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.assortedexplorations.com/$1 [R,L]
What all these achieve is to redirect insecure connections to secure ones for every visitor to the website. After that, internal hyperlinks without https
needed updating along with any forms so that a padlock sign could be shown for all pages.
With the main work completed, it was time to sort out a lingering niggle regarding the appearance of an FTP login page every time a WordPress installation or update was requested. The main solution was to make the web server account the owner of the files and directories, but the following line was added to wp-config.php as part of the fix even if it probably is not necessary:
define('FS_METHOD', 'direct');
There also was the non-operation of WP Cron and that was addressed using WP-CLI and a script from Bjorn Johansen. To make double sure of its effectiveness, the following was added to wp-config.php to turn off the usual WP-Cron behaviour:
define('DISABLE_WP_CRON', true);
Intriguingly, WP-CLI offers a long list of possible commands that are worth investigating. A few have been examined, but more await attention.
Before those, I still need to get my new VPS to send emails. So far, sendmail has been installed, the hostname changed from localhost and the server restarted. More investigations are needed, but what I have not is faster than what was there before, so the effort has been rewarded already.
Updating Piwik using the Linux Command Line
28th November 2016Because updating Piwik using its web interface has proved tempestuous, I have decided to update the self-hosted analytics application on an SSH session. The production web servers that I use are hosted on Linux systems, so that is why any commands apply to the Linux or UNIX command line only. What is needed for Windows servers may differ.
The first step is to down the required ZIP file with this command:
wget https://builds.piwik.org/piwik.zip
Once the download is complete, the contents of the ZIP archive are extracted into a new subfolder. This is a process that I carry out in a separate folder to that where the website files are kept before copying everything from the extraction folder in there. Here is the unzip command, and the -o
switch turns on overwriting of any previously existing files:
unzip -o piwik.zip
Without the required folder in the web server area to be updated, the next step is to do the actual system update that includes any updates to the Piwik database that you are using. There are two commands that you can use once you have specified the location of your Piwik installation. The second is needed when the first option cannot find where the PHP executable is stored. My systems had something more specific than these because both PHP 5.6 and PHP 7.0 are installed. Looking in /usr/bin
was enough to find what I needed to execute in place of PHP below. Otherwise, the command was the same.
./[path to piwik]/console core:update
php [path to piwik]/console core:update
While the upgrade is ongoing, it prompts you to permit it to continue before it goes and modifies the database. This did not take long on my systems, but that depends on how much data there is. Once, the process has completed, you can delete any extraneous files using the rm
command.
Setting the PHP version in .htaccess on Apache web servers
7th September 2014The default PHP version on my outdoors, travel and photography website is 5.2.17 and that is getting on a bit now since it is no longer supported by the PHP project and has not been thus since 2011. One obvious impact was Piwik, which I use for web analytics and needs at least 5.3.2. Since WordPress 4.0 will not work without having 5.2.24 or later, that upgrade became implausible. Therefore, I contacted Webfusion's support team, and they showed me how to get to at least 5.3.3 and even as far as 5.5.9. The trick is the addition of a line of code to the .htaccess
file (near the top was my choice) like one of the following:
PHP 5.3.x
AddHandler application/x-httpd-php53 .php
PHP 5.5.x
AddHandler application/x-httpd-php55 .php
When I got one of these in place, things started to look promising, but for a locked database due to my not watching how big it had got. Replacing it with two additional databases addressed the problem of losing write-access, though there was a little upheaval caused by this. Using PHP 5.5.9 meant that I spotted messages regarding the deprecation of the mysql_connect
function, so that needed fixing too. Prefixing it with @ might have been a temporary fix while I sought a more permanent one. Thus, I opted for piggybacking off what WordPress uses; make use of MySQLi
or PDO_MySQL
are other options. Sorting the database issue meant that I saw the upgrade message for WordPress as well as a mix of plugins and themes, so all looked better, leaving me to be less concerned about losing security updates. Also, I am up to the latest version of Piwik too, and that's an even better way to be.
Turning off the admin bar in WordPress 3.1
25th October 2010Work on WordPress 3.1 is in full swing at the moment, though I initially thought that they were taking a little break after 3.0. From what I can see, many refinements are being made to the multi-blog functionality and behind-the-scenes work is ongoing on the administration screens too.
Another under-the-bonnet change has been to make WordPress less tied to MySQL, since the possibility of dropping in support for an alternative such as PostgreSQL is now a reality even if it isn't part of the default package. For now, it looks as if this will be plugin territory rather than default multi-database support, though that may become a sensible development in the light of Oracle's acquisition of MySQL and its sabre-rattling regarding Java patents. So far, the change to WordPress has affected my use of its database engine to power an offline version of my online photo gallery, but a quick spot of code editing sorted that issue.
One more obvious alteration will be the addition of a WordPress.com style administration bar to the top of all content and administration screens for a user who is logged into the system. Though it will be turned on by default, there will be the option of turning it off for those among who prefer things that way. All that will be needed for this is to add the following line near the top of wp-config.php:
define( "WP_SHOW_ADMIN_BAR", false);
The chance to see new additions like those above and be ready for is my main reason for following WordPress development. It's best to be ready instead of being surprised, though it has to be said that the blogging or CMS platform is a very polished one these days.
Are ten seconds enough?
27th April 2009Fasthosts, the hosting provider for what you find here, has, in their wisdom, decided to limit the execution time for ASP scripts to 15 seconds and 10 seconds for any others. I haven't used Perl sufficiently in this shared hosting set up to determine how that is affected. In contrast, I can share my experiences on the PHP side and you may have noticed occasional glitches. They have also disabled the set_time_limit
PHP function, so you cannot easily address the matter yourself where you need to do it. You almost get the feeling that they don't trust the abilities, actions and oversight of their users. Personally, I reckon that the ten-second limit is too short and that something of the order of 20 or 30 seconds would be better. If it all gets too restrictive, I suppose that there are other providers, though I think that I would avoid resellers after a previous less than glorious experience. There's the dedicated server option too if I was feeling flush, not so likely given the economic times in which we live.
Investigating Textpattern
9th March 2009With the profusion of Content Management Systems out there, open source and otherwise, my curiosity has been aroused for a while now. In fact, Automattic's aspirations for WordPress (the engine powering this blog) now seem to go beyond blogging and include wider CMS-style usage. Though some may even have put the thing to those kinds of uses, I believe that it has a way to go before it can put itself on a par with the likes of Drupal and Joomla!.
Speaking of Drupal, I decided to give it a go a while back and came away with the impression that it's a platform for an entire website. At the time, I was attracted by the idea of having one part of a website on Drupal and another using WordPress, but the complexity of the CSS in the Drupal template thwarted my efforts and I desisted. The heavy connection between template and back end cut down on the level of flexibility too. Though that mix of different platforms might seem odd in architectural terms, my main website also had a custom PHP/MySQL-driven photo gallery too and migrating everything into Drupal wasn't going to be something that I was planning. Since I might have been trying to get Drupal to perform a role for which it was never meant, I am not holding its non-fulfillment of my requirements against it. While Drupal may have changed since I last looked at it, I decided to give an alternative a go regardless.
Towards the end of last year, I began to look at Textpattern (otherwise known as Txp) in the same vein, and it worked well enough after a little effort that I was able to replace what was once a visitor dossier with a set of travel jottings. In some respects, Though Textpattern might feel less polished when you start to compare it with alternatives like WordPress or Drupal, the inherent flexibility of its design leaves a positive impression. In short, I was happy to see that it allowed me to achieve what I wanted to do.
If I recall correctly, Textpattern's default configuration is that of a blog, which means that it can be used for that purpose. So, I got in some content and started to morph the thing into what I had in mind. Because my ideas weren't entirely developed, some of that was going on while I went about bending Txp to my will. Most of that involved tinkering in the Presentation part of the Txp interface, though. It differs from WordPress in that the design information like (X)HTML templates and CSS are stored in the database rather than in the file system à la WP. Txp also has its own tag language called Textile and, though it contains conditional tags, I find that encasing PHP in <txp:php></txp:php> tags is a more succinct way of doing things; only pure PHP code can be used in this way and not a mixture of such in <?php ?> tags and (X)HTML. A look at the tool's documentation together with a perusal of Apress' Textpattern Solutions got me going in this new world (it was thus for me, anyway). The mainstay of the template system is the Page, while each Section can use a different Page. Each Page can share components and, in Txp, these get called Forms. These are included in a Page using Textile tags of the form <txp:output_form form="form1" />. Style information is edited in another section and you can have several style sheets too.
The Txp Presentation system is made up of Sections, Pages, Forms and Styles. The first of these might appear in the wrong place when being under the Content tab would seem more appropriate but the ability to attach different page templates to different sections places their configuration where you find it in Textpattern and the ability to show or hide sections might have something to do with it too. As it happens, I have used the same template for all bar the front page of the site and got it to display single or multiple articles as appropriate using the Category system. Though it may be a hack, it appears to work well in practice. Being able to make a page template work in the way that you require really offers a considerable amount of flexibility; it allowed me to go with one sidebar rather than two as found in the default set up.
Txp also has the facility to add plugins (look in the Admin section of the UI) and this is very different from WordPress in that installation involves the loading of an encoded text file, probably for the sake of maintaining the security and integrity of your installation. I added the navigation facility for my sidebar and breadcrumb links in this manner, with back end stuff like Tiny MCE editor and Akismet coming as plugins too. While there may not be as many of these for Textpattern, the ones that I found were enough to fulfil my needs. If there are plugin configuration pages in the administration interface, you will find these under the Extensions tab.
To get the content in, I went with the more laborious copy, paste and amend route. Given that I was coming from the plain PHP/XHTML way of doing things, the import functionality was never going to do much for me with its focus on Movable Type, WordPress, Blogger and b2. The fact that you only import content into a particular section may displease some, too. Peculiarly, there is no easy facility for performing a Textpattern to Textpattern migration apart from doing a MySQL database copy. While some alternatives to this were suggested, none seemed to work as well as the basic MySQL route. Tiny MCE made editing easier once I went and turned off Textile processing of the article text. This was done on a case by case basis because I didn't want to have to deal with any unintended consequences arising from turning it off at a global level.
While on the subject of content, this is also the part of the interface where you manage files and graphics along with administering things like comments, categories and links (like a blog roll on WordPress). Of these, it is the comment or link facilities that I don't use, allowing me to turn comments off in the Txp preferences. So far, I am using categories to bundle together similar articles for appearance on the same page, while also getting to use the image and file management side of things as time goes on.
All in all, it seems to work well, even if I wouldn't recommend it to the sort of audience to whom WordPress might be geared. My reason for saying that is because it is a technical tool that is used best if you are prepared to your hands dirtier from code cutting than other alternatives. I, for one, don't mind that at all because working in that manner might actually suit me. Nevertheless, not all users of the system need to have the same level of knowledge or access; usefully, it is possible to set up users with different permissions to limit their exposure to the innards of the administration. In line with Textpattern's being a publishing tool, you get roles such as Publisher (administrator in other platforms), Managing Editor, Copy Editor, Staff Writer, Freelancer, Designer and None. Those names may mean more to others, but I have yet to check out what those access levels entail because I use it on a single user basis.
Txp may lack certain features, such as graphical visitor statistics instead of the current text listings. While, its administration interface could benefit from refinement, it fulfils my core requirements. The more streamlined approach makes it more practical in my opinion, which is demonstrated by my creation of A Wanderer's Miscellany. Consider exploring it yourself to see what's possible, since I am certain that I have only scratched the surface of Textpattern's capabilities.
Controlling the post revision feature in WordPress 2.6
21st July 2008While this may seem esoteric for some, I like to be in charge of the technology that I use. So, when Automattic included post revision retention to WordPress 2.6, I had my reservations about how much it would clutter my database with things that I didn't need. Thankfully, there is a way to control the feature, but you won't find the option in the administration screens (they seem to view this as an advanced setting and so don't want to be adding clutter to the interface for the sake of something that only a few might ever use); you have to edit wp-config.php yourself to add it. Here are the lines that can be added and the effects that they have:
Code: define('WP_POST_REVISIONS','0');
Effect: turns off post revision retention
Code: define('WP_POST_REVISIONS','-1');
Effect: turns it on (the default setting)
Code: define('WP_POST_REVISIONS','2');
Effect: only retains two previous versions of a post (the number can be whatever you want, so long as it's an integer with a value more than zero).
Update (2008-07-23):
There is now a plugin from Dion Hulse that does the above for you and more.
A reasonable requirement of an IDE
20th May 2008I have been having a play with NetBeans IDE Early Access for PHP and, while it has a lot to offer, one impression remains uppermost in my mind: it is so slow. While I might have a project with many files in it, start-up takes an age because of project checking. Other functionality such as text searching is far from speedy either. The sluggishness probably arises from this release being very early in its life cycle, and it reminds me of how slow older versions of the Java IDE were, even if this is slower. For PHP development, I'll be giving NetBeans a while to mature before taking another look at it.
On a similar note, I recently dispatched Quanta Plus from my system for sluggish start-ups and will not return to it because other alternatives such as Bluefish and Eclipse PDT fit my needs much better. I like my editors to be slick and responsive, and Quanta has been around long enough for any slowness to be knocked out of it. However, I get the feeling that the extras have added bloat, while I expect any additional functionality that I never use not to get in my way. It is for the latter reason that I was always able to get on with Dreamweaver and even run it on Ubuntu using the WINE library. If I really wanted a stripped out yet functional editor, Gedit would do most of what I need - it colour-codes syntax for a variety of languages for a start - but it's always handy to have a file system explorer window incorporated and I value any syntax checking and auto-completion as well. So, it looks as if Eclipse and Bluefish could be serving my needs for a while to come, alongside so use Dreamweaver for online editing of website files.