gdfgdfg gdfgdfg - 2 months ago 22
PHP Question

Generate unique slug Codeigniter 3 && MySQL

I need to generate unique slug based on user input with this code:

public function create_slug($id, $name){

$count = null;
$name = url_title($name);
while(true) {
$this->db->select('id');
$this->db->where('id !=', $id);
$this->db->where('slug', $name);
$query = $this->db->get('users');
if ($query->num_rows() == 0) {
break;
} else {
$name .= '-' . (++$count);
}
}
return $name;
}


It select everything that mach the slug (
$name
), except its own slug.
The result for first user input -
123
is slug -
123
. For second same input the slug is
123-1
, but third input with same text is with result
123-1-2
, which is not what I want.

I tried another way :

public function create_slug($id, $name){
$count = null;
$name = url_title($name);
$this->db->select('id');
$this->db->where('id !=', $id);
$this->db->where('slug', $name);

$query = $this->db->get('users');

if($query->num_rows()){
$count = '-' . ($query->num_rows() + 1);
}
return $name . $count;
}


Here, is same query, but count rows + 1.
For first
123
the slug is
123
;
Second
123
, slug
123-2
;
Third
123
, slug again
123-2
, which is not unique.

How can I create slug that is based on some user input and is unique and, if there is slug with value
name
, next will be
name-1
, if again, next will be
name-2
and etc. ?

Answer

You need to create a temp slug_name based on the original name, and test the slug_name. On fail, recreate new slug_name based on original name. On success (breaking out of the loop) return the amended slug_name.

public function create_slug($id, $name)
{
    $count = 0;
    $name = url_title($name);
    $slug_name = $name;             // Create temp name
    while(true) 
    {
        $this->db->select('id');
        $this->db->where('id !=', $id);
        $this->db->where('slug', $slug_name);   // Test temp name
        $query = $this->db->get('users');
        if ($query->num_rows() == 0) break;
        $slug_name = $name . '-' . (++$count);  // Recreate new temp name
    }
    return $slug_name;      // Return temp name
}

Or like this using count_all_results. Removed your id check as well as I presume the slug needs to be unique for the entire table.

public function create_slug($id, $name)
{
    $count = 0;
    $slug_name = $name = url_title($name);
    while(true) 
    {
        $this->db->from('users')->where('slug', $slug_name);
        if ($this->db->count_all_results() > 0) break;
        $slug_name = $name . '-' . (++$count);
    }
    return $slug_name;
}
Comments