Generate unique slugs in CakePHP

I believe it was WordPress who came up with the term “slug”. It has been adopted by many other systems though, and it basically means the following: a unique identifier which can be used in a URL to create a permalink to a page.

At least, that’s my interpretation of it. In this article I will show you how you can generate a unique slug easily when working with the CakePHP Framework.

Since the slug should be unique across records in the same database table, the best place to store slug-generating functionality is in the AppModel, which is, strictly speaking, the only business logic layer that may access the database.

If you haven’t got an AppModel created yet, add one in /app/app_model.PHP. You may fill it with the following code:

  1. <?php
  2. class AppModel extends Model {
  3. function createSlug ($string, $id=null) {
  4. $slug = Inflector::slug ($string,'-');
  5. $slug = low ($slug);
  6. $i = 0;
  7. $params = array ();
  8. $params ['conditions']= array();
  9. $params ['conditions'][$this->name.'.slug']= $slug;
  10. if (!is_null($id)) {
  11. $params ['conditions']['not'] = array($this->name.'.id'=>$id);
  12. }
  13. while (count($this->find ('all',$params))) {
  14. if (!preg_match ('/-{1}[0-9]+$/', $slug )) {
  15. $slug .= '-' . ++$i;
  16. } else {
  17. $slug = preg_replace ('/[0-9]+$/', ++$i, $slug );
  18. }
  19. $params ['conditions'][$this->name . '.slug']= $slug;
  20. }
  21. return $slug;
  22. }
  23. }
  24. ?>
  25. Download this code: /code/generate_unique_slugs_in_cakephp1.txt

Goal

What this code does, is providing a method, createSlug (), which can be accessed from all models in your application. It’ll normalize the string, make it URL-friendly and last but not least, it makes it unique.

To demonstrate the “unique” part, let’s say we’ve got a record with the title “I love CakePHP“. The createSlug method will turn this into “i-love-cakePHP“. Human friendly and search-engine friendly.
What happens when I wish to create two more items in my database called “I love CakePHP“? The createSlug method will generate the following two slugs: i-love-cakePHP-1 and i-love-cakePHP-2.

This way users can bookmark your URLs and always end up in the right place, even though the titles of your records may be similar.

How to use?

It’s simple, really. Since the method is created in the AppModel base class, you can invoke it from every model in your application. When saving a record, you can simply call…

  1. $slug = $this->generateSlug ('my title');
  2. Download this code: /code/generate_unique_slugs_in_cakephp2.txt

…from within your models, or…

  1. $slug = $this->MyModel->generateSlug ('my title');
  2. Download this code: /code/generate_unique_slugs_in_cakephp3.txt

…from within your controllers, right before you insert new data.

Note that you have to pass the id from the current record when you’re modifying existing records, so it can exclude that from its check, like this:

  1. $slug = $this->generateSlug ('my title', 10);
  2. Download this code: /code/generate_unique_slugs_in_cakephp4.txt

How does it work?

  1. $slug = Inflector::slug ($string,'-');
  2. $slug = low ($slug);
  3. Download this code: /code/generate_unique_slugs_in_cakephp5.txt

These lines normalize the string into a human friendly, easily readable slug.

[php]
$params = array ();
$params [‘conditions’]= array();
$params [‘conditions’][$this->name.’.slug’]= $slug;
if (!is_null($id)) {
$params [‘conditions’][‘not’] = array($this->name.’.id’=>$id);
}
[/php]

This code will create the $params array, which is used in checking wether or not a slug already exists.

[php]

while (count($this->find (‘all’,$params))) {
if (!preg_match (‘/-{1}[0-9]+$/’, $slug )) {
$slug .= ‘-‘ . ++$i;
} else {
$slug = preg_replace (‘/[0-9]+$/’, ++$i, $slug );
}
$params [‘conditions’][$this->name . ‘.slug’]= $slug;
}

[/php]

 

 

This while loop will append the slug with an incrementing value until no results are returned from the Model::find method. This ensures the final slug string is unique.

I’ve used this method in multiple projects now, and have found it very useful. I hope it’ll be of some use to you as well, and would like to know what you think this method can do better. Let me know in the comments!

Install PostgreSQL and phpPgAdmin in Windows with Wamp

All the PHP developers out here, who use Windows is familiar with WAMP. I the WAMP stack we get a lot of packages like sqlbuddy and phpmyadmin. But a project came to me that uses PostgreSQL. So I had to install PostgreSQL in Wamp. Well it was a tricky job to do. At last I did it. So today in this topic I am going to share this with the developers who need to use PostgreSQL in Windows and Wamp.

In this article I am going to use,

  1. WampServer 2.1. Download it from Here.
  2. PostgreSQL 9.1. Download it from Here.
  3. phpPgAdmin 5.0.2. Download it from Here.

It is assumed that, you have installed the WampServer already. Now, let us proceed with the new Installations.

  1. First, install the PostgreSQL. It is a simple installation procedure. Just click Next Until, when you come to the screen where you give the installation directory. Make it to your suitable directory. I installed it in “C:wampappsPostgreSQL”. Then provide the Data path according to “C:wampappsPostgreSQL9.1data”.
  2. Then you will be presented a Password Screen where you can give the main login password. I have made it as “root“.
  3. Then in the next screen you will be prompted with the Port number. Make sure it does not conflict with the MySQL port 3306. So I used the default as 5432.
  4. Set the Locale as the Default Locale.
  5. Now click on Next and it will start the installation.
  6. Next click on Finish. And we are done with the installations.
  7. Check installation of PostgreSQL by clicking Start ->Programs ->PostgreSQL 9.1 ->PgAdmin III.
  8. Click on Server(1) and Right Click on PostgreSQL Database Server 9.1 (localhost:5432) and Select Connect to obtain a connection to server and give password. It will connect to Database server.
  9. Now it is time to bridge PHP to it. So Go on the task bar and Left Click on the Wamp Tray icon. Navigate to PHP > PHP extension. Then enable,
    1. php_pgsql
    2. php_pdo_pgsql extension.
  10. Restart the Wampserver. This time you will probably see some errors saying like,
    1. PHP Warning:  PHP Startup: Unable to load dynamic library  ‘C:wampbinphpphp5.3.5extphp_pdo_pgsql.dll’ – The specified module could not be found.
    2. PHP Warning:  PHP Startup: Unable to load dynamic library ‘C:wampbinphpphp5.3.5extphp_pgsql.dll’ – The specified module could not be found.
  11. To eleminate them you need to copy libpq.dll from wampbinphpphp5.3.5 to  wampbinapacheApache2.2.17bin. Again restart the Wamp Server. By now we are done with the php configuration. Next we will install phpPgAdmin and use it.
  12. So download phpPgAdmin and copy it in C:wampapps assuming, Wampserver is in C Drive. So the path will be, C:wampappsphpPgAdmin-5.0.2.
  13. To make a shortcut in Wamp Index page in the Your Aliases section create a file called, phppgadmin.conf in C:wampalias. And copy paste the following,
    Alias /phppgadmin "C:/wamp/apps/phpPgAdmin-5.0.2/" 
    
    <Directory "C:/wamp/apps/phpPgAdmin-5.0.2/">
        Options Indexes FollowSymLinks MultiViews
        AllowOverride all
            Order Deny,Allow
    	Allow from all
    </Directory>
  14. Restart the Wamp server and go to http://localhost/. You will see a link came under Your Aliases  as phppgadmin. Click on that link and you will see the following screen.
    Login phppgadmin
  15. Then click on the PostgreSQL link on the left hand side. You will be prompted for the username and the password. By default postgrey creates an user called postgres. So give it in the username field and give the password same as you have entered in the time of the installation. For me it is root.
    pgadmin login username and password
  16. Last we will see the following screen after successful login.
    phppgadmin database browser screen
  17. Last is is time to test a simple database connection PHP script. So to do that, create a database called test and create a php page with the following code in it.
    <?php
    $con="host=localhost port=5432 dbname=test user=postgres password=root";
    $db=pg_connect($con) or die('connection failed');
    echo 'Connected to: ', pg_dbname($db);
    ?>

    If it does not show any error, then we are good to go. We can use PostgreSQL.

  18. If you face any problem then you can write to me. I will try to solve the problem.

Initialize a new WordPress in different folder

Say you have WordPress installed in root. And in root you also have a folder ‘cool’.

With this code you can use all WP functions, by initializing it:

[php]

define(‘WP_USE_THEMES’, true);
if ( !isset($wp_did_header) ) {
$wp_did_header = true;
require_once( ‘../wp-load.php’ );
wp();
require_once( ‘../wp-settings.php’ );
}

$the_slug = ‘sidebar-oku’;
$args=array(
‘name’ => $the_slug,
‘post_type’ => ‘post’,
‘post_status’ => ‘publish’,
‘numberposts’ => 1
);

$my_posts = get_posts($args);
echo apply_filters(‘the_content’, $my_posts[0]->post_content);

[/php]

This script is actually used in combination with AJAX CrossDomain.

[javascript]

jQuery(document).ready(function($){

$(‘#fromster’).html(
‘ $the_slug,
‘post_type’ => ‘post’,
‘post_status’ => ‘publish’,
‘numberposts’ => 1
);

$my_posts = get_posts($args);
echo str_replace(array(“r”, “n”), ”, $my_posts[0]->post_content);
//echo ‘daniel’;
?>’
);
$(‘#fromster’).fadeIn(‘slow’);

$(‘#Bottom’).html(
‘ $the_slug,
‘post_type’ => ‘post’,
‘post_status’ => ‘publish’,
‘numberposts’ => 1
);

$my_posts = get_posts($args);
echo str_replace(array(“r”, “n”), ”, $my_posts[0]->post_content);
//echo ‘daniel’;
?>’
);
$(‘#super_footer’).fadeIn(‘slow’);

});

[/javascript]

The above code is placed inside aurelie.no/_devoku/read.php

Then, in devoku’s template file ‘sidebar2.php’ I have:

[html]

jQuery(document).ready(function($){
$.ajax({
url:             “//aurelie.no/_devoku/read.php”,
dataType:        “jsonp”,
crossDomain:    true,
data:            {n: “right_sidebar”}
})
.done(function(data){
console.log(data.responseText);
});
});

[/html]

And in page-footer.php

[html]

jQuery(document).ready(function($){
$.ajax({
url:             “//aurelie.no/_devoku/read.php”,
dataType:        “jsonp”,
crossDomain:    true,
data:            {n: “footer”}
})
.done(function(data){
console.log(data.responseText);
});
});

Improve performance on dev.oku.no

* moved the navigation.js
from functions.php I commented
wp_enqueue_script( ‘twentyoku-navigation’, get_template_directory_uri() . ‘/js/navigation.js’, array(), ‘1.0’, true );

and moved the minimized navigation.js content to footer.php

=================================

* removed query strings from static resources:
in functions.js I added

function vc_remove_wp_ver_css_js( $src ) {
if ( strpos( $src, ‘ver=’ ) )
$src = remove_query_arg( ‘ver’, $src );
return $src;
}
add_filter( ‘style_loader_src’, ‘vc_remove_wp_ver_css_js’, 9999 );
add_filter( ‘script_loader_src’, ‘vc_remove_wp_ver_css_js’, 9999 );