get unique slug in codeigniter - php

I want to get unique slug for my articles. I am using codeigniter. I was wondering to have some thing like sample-title-1 and sample-title-2 if there are two articles that have the same title like codeignier does with file upload filename(:num) . I could not figure out a way to do it. I am not an expert on codeigniter. I am learning it.
I prepared a function, when passed a string $str it checks if the slug exists, if it does, it adds the ID of that article to the end of that slug and returns it, if not, it returns the slug.
It is working fine and serving the purpose of unique slug. But what I wanted was to have something like sample-title-1 and sample-title-2 . Is there any way to do so?
$data['slug'] = $this->get_slug($data['title']);
public function get_slug ($str)
{
$slug = url_title($str, 'dash', true);
// Do NOT validate if slug already exists
// UNLESS it's the slug for the current page
$id = $this->uri->segment(4);
$this->db->where('slug', $slug);
! $id || $this->db->where('id !=', $id);
$category = $this->category_m->get();
if (count($category)) {
return $slug.$id;
}
return $slug;
}

easy to use and really helpful to create unique slugs have look on CI slug library
read its documentation to implement it.

what i used to do is to make slug db field UNIQUE.
Then easly do all with the CI helpers Url Helper and Text Helper
$last_id_inserted = //get from db the last post's ID;
$post_title = "My slug would be";
$slug = mb_strtolower(url_title(convert_accented_characters($post_title))).'-'.$last_id_inserted;
echo $slug;
//outputting my-slug-would-be-123
//insert the new post with slug
So ID will be unique and slug too.

I think you need something like that:
//Database loaded
//Text helper loaded
function post_uniq_slug($slug, $separator='-', $increment_number_at_end=FALSE) {
//check if the last char is a number
//that could break this script if we don't handle it
$last_char_is_number = is_numeric($slug[strlen($slug)-1]);
//add a point to this slug if needed to prevent number collision..
$slug = $slug. ($last_char_is_number && $increment_number_at_end? '.':'');
//if slug exists already, increment it
$i=0;
$limit = 20; //for security reason
while( get_instance()->db->where('slug', $slug)->count_all_results('posts') != 0) {
//increment the slug
$slug = increment_string($slug, $separator);
if($i > $limit) {
//break;
return FALSE;
}
$i++;
}
//so now we have unique slug
//remove the dot create because number collision
if($last_char_is_number && $increment_number_at_end) $slug = str_replace('.','', $slug);
return $slug;
}
Examples:
post_uniq_slug('sample'); //"sample" exists
//sample-1
post_uniq_slug('sample-2013'); //"sample-2013" exists
//sample-2013-2
post_uniq_slug('sample-2013', '-', TRUE); //increment "sample-2013"
//sample-2014
*NOT TESTED

public function create_slug($name)
{
$table='tradeshow'; //Write table name
$field='slug'; //Write field name
$slug = $name; //Write title for slug
$slug = url_title($name);
$key=NULL;
$value=NULL;
$i = 0;
$params = array ();
$params[$field] = $slug;
if($key)$params["$key !="] = $value;
while ($this->db->from($table)->where($params)->get()->num_rows())
{
if (!preg_match ('/-{1}[0-9]+$/', $slug ))
$slug .= '-' . ++$i;
else
$slug = preg_replace ('/[0-9]+$/', ++$i, $slug );
$params [$field] = $slug;
}
return $alias=$slug;}

Related

Laravel default pagination breaking with filter on the same table

I am using Laravel 9 and am displaying some data using the paginate method on the database. I also have a search field above my table and use it to filter out the result. While filtering, I filter the data and call the paginate method on it too. That's where the issue arises. Let's say I was on page number 6 before filtering and after filtering the result sums up in two page, but the paginate method redirect me to page 6 which in turn will show no results.
Below is my code example:
For the first time page:
$modelData = Model::orderBy('id', 'DESC')->paginate(20);
After filtering:
$search = $_GET['searchField'];
$modelData = Model::where("name", "LIKE", "%{$search}%")->paginate(2);
I was expecting it to take me to the first page of the result, but it takes me the the page where i searched my list from.
EDIT:
My Complete function:
public function index()
{
$sortData = $searchData = NULL;
//CHECKS FOR SORTING, SEARCH AND BOTH
if (isset($_GET['sort']) && !empty($_GET['sort']) && isset($_GET['searchField']) && !empty($_GET['searchField'])) {
$search = $_GET['searchField'];
$modelData = Model::where("name", "LIKE", "%{$search}%")->orderBy($_GET['sort'], $_GET['direction'])->paginate(10);
$sortData = $_GET;
$searchData = $search;
} elseif (isset($_GET['sort']) && !empty($_GET['sort'])) {
$modelData = Model::orderBy($_GET['sort'], $_GET['direction'])->paginate(10);
$sortData = $_GET;
} elseif (isset($_GET['searchField']) && !empty($_GET['searchField'])) {
$search = $_GET['searchField'];
$modelData = Model::where("name", "LIKE", "%{$search}%")->paginate(10);
$searchData = $search;
} else {
$modelData = Model::orderBy('id', 'DESC')->paginate(10);
}
return view('content.view.list', compact(
'modelData',
'sortData',
'searchData'
));
}
I think you should not use $_GET
$request->query('sort')
$request->query('direction')
Since you use !empty(), you don't need to use isset().
You don't need $search, because
$search = $_GET['searchField'];
...
$searchData = $search;
So
$searchData = $_GET['searchField'];
You don't need $searchData,too. Because $sortData = $_GET.
You already have whole $_GET, why do you want to define one of it's element again? $sortData['searchField']
I think the English meaning of searchData is better than sortData. Becuar sortData means the data needed to sort, to order by. While searchData means the data needed to do the search task, do the filtering work. So searchData should be the $_GET.
I suggest:
public function index()
{
$searchData= $request->query(); // This is $_GET
// See what is your $_GET
//echo "<pre>".print_r($searchData, 1)."</pre>"; exit;
$model = Product::query(); //Initialize query builder
if(!empty($searchData['searchField']))){
$model->where('name', 'LIKE', '%'.$searchData['searchField'].'%');
}
if(!empty($searchData['sort']))){
$sort = $searchData['sort'];
}else{
$sort = 'id'; // default use id
}
if(!empty($searchData['direction'])){
$direction = $searchData['direction'];
}else{
$direction = 'DESC'; // default use desc
}
$model->orderBy($sort, $direction);
// This can see the SQL content, and it should before result like paginate() or get(). I think...
if(!empty($searchData['debug'])){
$debugData['sql'] = $query->toSql();
$debugData ['bidings'] = $query->getBindings();
echo "<pre>".print_r($debugData , 1)."</pre>"; exit;
}
if(!empty($searchData['limit'])){
$limit = $searchData['limit'];
}else{
$limit = 10;
}
$modelData = $model->paginate($limit)->appends($queries);
return view('content.view.list', compact(
'searchData',
'modelData',
));

Laravel Slug Exist

I want to create slug for blog categories. I do it like this;
Str::slug($request->title)
But I have to check if slug exist. If exist, I want to do like this;
// For example title is test. Slug must be test.
// But if slug exist I want to do it test1
if(count(blog_tags::where('slug',$slug)->get()) > 0){
$slug = $slug . '1';
}
// But test1 too can be exist. So I have to test it.
If I test it again and again, system will be slow. What should I do?
Add the following function in your controller class to check ending number in slug
protected function countEndingDigits($string)
{
$tailing_number_digits = 0;
$i = 0;
$from_end = -1;
while ($i < strlen($string)) :
if (is_numeric(substr($string, $from_end - $i, 1))) :
$tailing_number_digits++;
else :
// End our while if we don't find a number anymore
break;
endif;
$i++;
endwhile;
return $tailing_number_digits;
}
Add the following function in your controller class to check slug already exists or not
protected function checkSlug($slug) {
if(blog_tags::where('slug',$slug)->count() > 0){
$numIn = $this->countEndingDigits($slug);
if ($numInUN > 0) {
$base_portion = substr($slug, 0, -$numInUN);
$digits_portion = abs(substr($slug, -$numInUN));
} else {
$base_portion = $slug . "-";
$digits_portion = 0;
}
$slug = $base_portion . intval($digits_portion + 1);
$slug = $this->checkSlug($slug)
}
return $slug
}
Now you will get a unique incremental slug
$slug = $this->checkSlug(Str::slug(string));

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. ?
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;
}

Cakephp update or add new record

I have an image upload that adds the filename to a table called attachments. If the id already exists then I want it to update and if not then create a new record. At the moment it creates a new record so I have multiple records forthe one id. The id's are from a table called Addon's.
I am not sure how to do this in cakephp.
if (!empty($this->data)) {
$this->layout = null;
//if(empty($this->data['AddOn']['id'])){unset($this->data['AddOn']);}
// restructure data for uploader plugin // NEED TO GET RID OF THIS ? MOVE IT
$tmp_file = $this->data['Attachment'][0]['file'];
$tmp_file['extension'] = array_reverse(explode('.', $tmp_file['name']));
$tmp_file['extension'] = $tmp_file['extension'][0];
$tmp_file['title'] = strtolower(substr($tmp_file['name'],0,(0-strlen('.'.$tmp_file['extension']))));
$this->data['Attachment'][0]['alternative'] = ucwords(str_replace('_',' ', $tmp_file['title']));
$previous = $this->AddOn->Attachment->find('first', array('conditions'=> array('model'=>'AddOn', 'foreign_key'=>$id)));
if( !empty( $previous ) ) {
$this->AddOn->Attachment->id = $previous[ 'Attachment' ][ 'id' ];
}
if ($this->AddOn->save($this->data, array('validate' => 'first'))) {
$id = $this->AddOn->Attachment->getLastInsertID();
$att = $this->AddOn->Attachment->query("SELECT * from attachments WHERE id = ".$id);
$this->set('attachment',$att[0]['attachments']);
} else {
$tmp_file['name'] = 'INVALID FILE TYPE';
}
//debug($this->data);
$this->set('file', $tmp_file);
$this->RequestHandler->renderAs($this, 'ajax');
$this->render('../elements/ajax');
}
save() and saveAll() automatically update an existing row if the id has been set. You can do something like:
$previous = $this->AddOn->Attachment->find( /* whatever conditions you need */ );
if( !empty( $previous ) ) {
$this->AddOn->Attachment->id = $previous[ 'Attachment' ][ 'id' ];
}
Now the old record will be updated if it exists.
As a side note, the code after a successful saveAll() doesn't make much sense: first you're saving data to the database, then immediately retrieving it again. You can just keep using $this->data that already has the same content.
And another side note: you should use query() only as a last resort when you can't use Cake's other methods. query("SELECT * from attachments WHERE id = ".$id) is a trivial case that can be rewritten as $this->Model->id = $id; $this->Model->read(); or using a simple $this->Model->find() query.

WordPress Get the Page ID outside the loop

I want to get the page ID before starting the loop in WordPress. I am using
$page = get_query_var('page_id');
Apparently, it returns nothing.
I just want to check a page for its ID and add a class to <body> tag based on it.
If you're using pretty permalinks, get_query_var('page_id') won't work.
Instead, get the queried object ID from the global $wp_query:
// Since 3.1 - recommended!
$page_object = get_queried_object();
$page_id = get_queried_object_id();
// "Dirty" pre 3.1
global $wp_query;
$page_object = $wp_query->get_queried_object();
$page_id = $wp_query->get_queried_object_id();
You can also create a generic function to get the ID of the post, whether its outside or inside the loop (handles both the cases):
<?php
/**
* #uses WP_Query
* #uses get_queried_object()
* #see get_the_ID()
* #return int
*/
function get_the_post_id() {
if (in_the_loop()) {
$post_id = get_the_ID();
} else {
global $wp_query;
$post_id = $wp_query->get_queried_object_id();
}
return $post_id;
} ?>
And simply do:
$page_id = get_the_post_id();
Use this global $post instead:
global $post;
echo $post->ID;
If you by any means searched this topic because of the post page (index page alternative when using static front page), then the right answer is this:
if (get_option('show_on_front') == 'page') {
$page_id = get_option('page_for_posts');
echo get_the_title($page_id);
}
(taken from Forrst | Echo WordPress "Posts Page" title - Some code from tammyhart)
If you're on a page and this does not work:
$page_object = get_queried_object();
$page_id = get_queried_object_id();
you can try to build the permalink manually with PHP so you can lookup the post ID:
// get or make permalink
$url = !empty(get_the_permalink()) ? get_the_permalink() : (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$permalink = strtok($url, '?');
// get post_id using url/permalink
$post_id = url_to_postid($url);
// want the post or postmeta? use get_post() or get_post_meta()
$post = get_post($post_id);
$postmeta = get_post_meta($post_id);
It may not catch every possible permalink (especially since I'm stripping out the query string), but you can modify it to fit your use case.
I have done it in the following way and it has worked perfectly for me.
First declared a global variable in the header.php, assigning the ID of the post or page before it changes, since the LOOP assigns it the ID of the last entry shown:
$GLOBALS['pageid] = $wp_query->get_queried_object_id();
And to use anywhere in the template, example in the footer.php:
echo $GLOBALS['pageid];
You can use is_page($page_id) outside the loop to check.
This function get id off a page current.
get_the_ID();
Use below two lines of code to get current page or post ID
global $post;
echo $post->ID;
This is the correct code.
echo $post->ID;
If you are out of the Loop of WordPress you can not use any of the method of wordpress so you must use pure php.
You can use this code. And sure will help you :)
$page_id = #$_GET['page_id'];
if (!is_numeric($page_id)) {
// Then the uri must be in friendly format aka /my_domain/category/onepage/
// Try this
//$path = '/www/public_html/index.php/';
///$path = '/my_domain/category/onepage/';
$path = $_SERVER['REQUEST_URI'];
// Clean the uri
//$path = str_replace('/', '', $page);
$path = str_replace('.php', '', $path);
//$path = str_replace('?s=', '', $path);
$path = $path ? $path : 'default';
$path_len = strlen($path);
$last_char = substr($path, $path_len -1);
//echo $last_char;
$has_slash = strpos($last_char, "/");
//echo $has_slash;
if ($has_slash === 0) :
$path = substr($path, 0, $path_len -1);
elseif ($has_slash === null) :
$path = substr($path, 0, $path_len);
endif;
//echo "path: ".$path; // '/www/public_html/index'
$page = substr(strrchr($path, "/"), 1);
echo "page: ".$page; // 'index'
}
$my_page_id = 31;
$my_page = 'mypage';
//echo "page: ".$page;
//echo "page_id ".$page_id;
if($page_id == $my_page_id || $page == $my_page)
{
// your stuff....
}
Enjoy!

Categories