Rewrite the url using CodeIgniter - codeigniter

I read a lot of forum topics but I did not found any answer which meets my needs.
I am running a blog system and my current urls for each article look like: www.example.com/controller/method/id. However, for each article I have a title stored in a database, and would like to use that title in the url, so it would look like this: www.example.com/title

Hello there you are asking for a whole lot of code and you did not do any research yourself.
The best way is to use id with your title: http://www.example.com/id/long-title it is much better than using only title, because:
same title can occur more than once (creates problem that can be avoided)
slow loading/searching due querying by slug instead of ID (slow performance)
user needs to remember whole title (with id+title; user can copy partially broken url www.example.com/234593/this-title-is-) / opinion based
In order to make my proposal work you need to:
set up routes (application/config/routes.php)
//leave two CodeIgniter's routes on top
$route['default_controller'] = "welcome";
$route['404_override'] = '';
//leave this two routes in this order + make them LAST routes
$route['(:num)'] = 'blog/post/$1'; //if only id is in url
$route['(:num)/(:any)'] = 'blog/post/$1/$2'; //if id and title is in url
set up controller (application/controllers/blog.php)
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Blog extends CI_Controller {
public function __construct()
{
parent::__construct();
//load models helpers etc if not autoloaded
$this->load->helper('url');
}
public function index()
{
echo 'should throw 404 or redirect home because id was not provided';
}
public function post($id = null, $title = '')
{
if (!$this->validId( $id )) redirect(); //redirect somewhere because id of post is invalid search/404/home...
if (empty(trim($title))) {
redirect(base_url().$id.'/'.$this->getTitle($id), 'location', 301); //redirect to same page search engines friendly (301 header)
}
//display what you need
echo 'params; id: ' . $id . ' title: ' . $title;
}
private function validId($id)
{
if (is_numeric($id))
return true; //use database to check validity in this case every id is valid
}
private function getTitle()
{
//id should be good to use at this point
//get title using database
return $this->seoUrl('How you react of crying babies will determine their future.'); //made up title
}
private function seoUrl($string)
{
//source: http://stackoverflow.com/a/11330527/1564365
//Lower case everything
$string = strtolower($string);
//Make alphanumeric (removes all other characters)
$string = preg_replace("/[^a-z0-9_\s-]/", "", $string);
//Clean up multiple dashes or whitespaces
$string = preg_replace("/[\s-]+/", " ", $string);
//Convert whitespaces and underscore to dash
$string = preg_replace("/[\s_]/", "-", $string);
return $string;
}
}
/* End of file blog.php */
/* Location: ./application/controllers/blog.php */
thats it, now create yourself model that can validate ID, grab title...
sample code (of model):
public function isInDb($table, $where = array())
{
$q = $this->db->get_where($table, $where);
return ($q->num_rows() > 0) ? true : false; //returns either true or false, pretty straight forward
}
public function getColumn(){}
Now you use (generate) url www.example.com/1 (this will redirect with 301 header to /1/title) or you can use (generate) www.example.com/1/title link, however if you generate url like: /1/fake-title (title is invalid for id 1 it will not redirect to the correct one)
This solution is SEO friendly.

Related

how to hide id from url in Laravel 6?

hide id from url
https://wallpaperaccess.in/photo/162/download-wallpaper
i want url like this
https://wallpaperaccess.in/photo/download-wallpaper
ImagesController.php
public function show($id, $slug = null ) {
$response = Images::findOrFail($id);
$uri = $this->request->path();
if( str_slug( $response->title ) == '' ) {
$slugUrl = '';
} else {
$slugUrl = '/'.str_slug( $response->title );
}
$url_image = 'photo/'.$response->id.$slugUrl;
//<<<-- * Redirect the user real page * -->>>
$uriImage = $this->request->path();
$uriCanonical = $url_image;
if( $uriImage != $uriCanonical ) {
return redirect($uriCanonical);
}
Route
// Photo Details
Route::get('photo/{id}/{slug?}','ImagesController#show');
NOTE: i don't have any slug column in database, so can we use title as slug?
You should add a column field slug and auto-generate it from title
use Illuminate\Support\Str;
$slug = Str::slug($request->input('title'), '-');
In Models\Image.php
public function getRouteKeyName()
{
return 'slug';
}
In routes\web.php
Route::get('photo/{image:slug}','ImagesController#show');
In app\Http\Controllers\ImagesController.php
use app\Models\Image.php;
...
public function show(Image $image)
{
// controller will automatically find $image with slug in url
// $image_id = $image->id;
return view('your.view', ['image' => $image]);
}
In order to use a slug in the URL instead of an id, you'll need to...
Create a column in your table where you store the slug. A good way to make a slug unique is to append the actual id at the end. If you really don't want to see the id anywhere, you have no choice, you'll have to ensure the slug is unique yourself (there are a lot of ways to achieve this).
This is one way to automatically create an unique slug:
Make sure the slug column is nullable, then open your model and add these methods.
They are called "model events".
created is called when the model is, well, created.
updating is called when you are updating the model but before it's actually updated.
Using created and updating should automatically create the slug when you create or update a Images instance.
protected static function booted()
{
parent::booted();
static::created(function (Images $images) {
$images->slug = Str::slug($images->title.'-'.$images->id);
$images->save();
});
static::updating(function (Images $images) {
$images->slug = Str::slug($images->title.'-'.$images->id);
});
}
From a SEO point of view, updating the slug when the title change is arguably not a good practice, so you might want to omit this part (static::updating...), it's up to you.
Go to your model and add the following method:
/**
* Get the route key for the model.
*
* #return string
*/
public function getRouteKeyName()
{
return 'slug'; //or whatever you call the slug column
}
This way, the router will resolve your model by the slug, not the id.
In your route file, remove the id and change the name of the slug to match the name of your model:
Route::get('photo/{images}','ImagesController#show'); //here I'm assuming your model is Images from what I see in your controller
In your controller, change the declaration of your show method to this:
public function show(Images $images)
{
dd($images);
// if you did all this correctly, $images should be the Images corresponding to the slug in the url.
// if you did something wrong, $images will be an empty Images instance
//
//
// your code...
}
Images should be renamed to Image, models should not be plural. However, it should not make any difference here.

How to fetch session data in codeigniter?

I am trying to create a login process using codeigniter framework. Form validation is working but there is a problem in session. I can't fetch username after "Welcome-".
controller : Main.php
<?php
class Main extends CI_Controller
{
public function login()
{
$this->load->view('login');
}
public function login_validation()
{
$this->form_validation->set_rules('username','Username','required');
$this->form_validation->set_rules('password','Password','required');
if ($this->form_validation->run())
{
$username = $this->input->post('username');
$password= $this->input->post('password');
//model
$this->load->model('myModel');
if ($this->myModel->can_login($username,$password))
{
$session_data = array('username' => $username);
$this->session->set_userdata('$session_data');
redirect(base_url().'main/enter');
}
else
{
$this->session->set_flashdata('error','Invalid Username Or Password');
redirect(base_url().'main/login');
}
}
else
{
$this->login();
}
}
function enter()
{
if ($this->session->userdata('username')!=' ')
{
echo '<h2> Welcome- '.$this->session->userdata('username').'</h2>';
echo 'Logout';
}
else
{
redirect(base_url().'main/login');
}
}
function logout()
{
$this->session->unset_userdata('username');
redirect(base_url().'main/login');
}
}
?>
Add session library in the constructor
<?php
class Main extends CI_Controller
{
public function __construct()
{
parent::__construct();
// Load form helper library
$this->load->helper('form');
// Load form validation library
$this->load->library('form_validation');
// Load session library
$this->load->library('session');
$username = $this->session->userdata('username');
if (empty($username)) {
redirect('main/logout');
}
}
}
Another method you can load the session library in autoload.php file
File location: application/config/autoload.php
$autoload['libraries'] = array('database', 'email', 'session');
I suggest a slight code rearrangement for enter() that provides a better test for the user name using a tiny bit less code.
function enter()
{
if(empty($this->session->userdata('username')))
{
//base_url() accepts URI segments as a string.
redirect(base_url('main/login'));
}
// The following code will never execute if `redirect()` is called
// because `redirect()` does not return, it calls `exit` instead.
// So, you do not need an `else` block
echo '<h2> Welcome- '.$this->session->userdata('username').'</h2>';
echo 'Logout';
}
empty() will be true for an empty string, NULL, False and a couple of other things. In this case, you are most interested in an empty string or NULL. (empty() documentation HERE.)
You might want to consider adding 'trim' to your validation rules because it strips empty whitespace from the input string. That will remove the possibility of someone trying to input a username using only space characters.
Otherwise, your code should work. If it does not then it's very likely you do not have CodeIgniter sessions configured properly. There are many session setup questions answered here on Stack Overflow that will help you get it running.

How to deal with multilingual uri redirect on Codeigniter?

I'm building a multilingual site under Codeigniter 3.0 and I'd like to have this behavior:
The default language of the site is 'en'.
When user visits site (/), it gets browser's Accept-language and stores it in session var. Then I check if language is 'en' or not. If not, it redirects to mysite.com/lang. Case language is not 'en', do nothing so it keeps mysite.com/
The problem is that CI takes /lang as a controller.
I edited routes.php as following:
$route['es'] = '/';
$route['en'] = '/';
$route['de'] = '/';
But now I'm on a "too many redirects" issue as routes.php redirects to / when coming from /language and in my controller redirects to /language
My controller:
class Checklanguage {
public $CI;
/**
* Constructor.
*/
public function __construct()
{
if (!isset($this->CI))
{
$this->CI =& get_instance();
}
$this->CI->load->library('session');
}
public function redirect_if_not_default()
{
/* LANGUAGES SECTION */
$browserLang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
// if browser has no language, we use 'en'
if (strlen($browserLang) != 2) $browserLang = 'en';
// retrieve session lang (maybe NULL)
$sessionLang = $this->CI->session->userdata('lang');
// determine which language use
// if user has not set any language, we use browser lang
if(!isset($sessionLang)) $preferredLang = $browserLang;
// if user has changed language, we use session language
if (strlen($sessionLang) == 2) {
$preferredLang = $sessionLang;
}
// redirect if language is not 'en'
if ($preferredLang != 'en') {
header('Location: /'.$preferredLang);
}
}
}
How can I solve this?
Thanks
Try:
if ($preferredLang != 'en') {
redirect(base_url()."/$preferredLang");
}
Addition:
if you are using CI language class for that, all you need to setup a language file inside application/language and then load that language in controller.
CI documentation

Obtain CodeIgniter links that consider routes.php

How can I link pages in my site considering routes.php?
Example:
$route['login'] = 'user/login';
The code above allows me to see "user/login" visiting just "login". But how can I link to that page using the internal route (user/login) and get as a result the "external route" "login".
I think it's important because I could change my URLs just modifiying "routes.php" and linking everything with internal routes.
From a Drupal perspective I can have my internal route "node/1" and the external url could be "about-us". So if I use "l('node/1')" this will return "about-us". Is there a function like "drupal_get_path_alias"?
Right now I can't find anything in the CI docs that point me to the right direction.
Thanks for your help.
You could have a look at using something like
http://osvaldas.info/smart-database-driven-routing-in-codeigniter
This would allow you to have the routes configured in the database. Then if you want to dynamically create you links through a model like this:
class AppRoutesModel extends CI_Model
{
public function getUrl($controller)
{
$this->db->select('slug');
$this->db->from('app_routes');
$this->db->where('controller', $controller);
$query = $this->db->result();
$data = $query->row();
$this->load->library('url');
return base_url($data->slug);
}
public function getController($slug)
{
$this->db->select('controller');
$this->db->from('app_routes');
$this->db->where('slug', $slug);
$query = $this->db->result();
$data = $query->row();
return $data->controller;
}
}
These have not been fully tested but will hopefully give you the general idea.
I hope this helps you :)
Edit------------------------------
You can create a routes_helper.php and add a function like
//application/helpers/routes_helper.php
function get_route($path)
{
require __DIR__ . '/../config/routes.php';
foreach ($route as $key => $controller) {
if ($path == $controller) {
return $key;
}
}
return false;
}
$this->load->helper('routes');
echo get_route('controller/method');
This does roughly what you want although this method does not support the $1 $2 etc vars that can be added to reflect the :num or :any wildcard that exist. You can edit the function to add that functionality but this will point you in the right direction :D
You can do that with .htaccess file:
Redirect 301 /user/login http://www.example.com/login

Redirection In index.php page in Codeigniter

Iam developing a site in codeigniter.This is my url http://myserver.net/visio/UBwXo.
Here http://myserver.net/visio/ is my base_url.
After /visio/ here have a variable.When there have any value after /visio/ then i wantto take the corresponding url from database to this value.
That means in my database,
UBwXo => "*any url***"
jshom => "*any url***"
So when getting value after /visio/ i want to take the corresponding url from databse and redirect it in to that url without using htaccess.
I want to done this redirection process in index.php page of root folder.
Is this possible?
The orginal url for http://myserver.net/visio/UBwXo like myserver.net/visio/index.php/admin/index/UBwXo
the default controller is admin
First, create redirect.php file in the controllers folder (application/controllers) and add this code to this file:
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class Redirect extends CI_Controller
{
/**
* Method to redirect from an alias to a full URL
*/
public function index()
{
$alias = $this->uri->segment(1);
$this->db->select('url');
$query = $this->db->get_where('links', array('alias' => $alias), 1, 0);
if ($query->num_rows() > 0)
{
foreach ($query->result() as $row)
{
$this->load->helper('url');
redirect($row->url, 'refresh', 301);
}
}
else
{
echo "Sorry, alias '$alias' not found";
}
}
}
Then create table in your database. Your table must be like this:
CREATE TABLE IF NOT EXISTS `links` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`alias` varchar(6) CHARACTER SET utf8 DEFAULT NULL,
`url` text CHARACTER SET utf8,
PRIMARY KEY (`id`),
UNIQUE KEY `alias` (`alias`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;
After that, set default controller value to the redirect class.
Open application/config/routes.php. Find $route['default_controller'] , then set redirect as a value to this variable, like this:
$route['default_controller'] = "redirect";
Then enjoy life ;)
EDIT:
I had forgotten to mention URI routing in config/routes.php for redirecting:
$route[':any'] = "redirect/index/$1";
Your best resource here will be the CodeIgniter guides, specifically the page on Controllers. The section on Remapping Function calls should be exactly what you need in this case.
Since the default behavior is to look for a controller method with the name of the first segment after the base url, we need to change this to pass it as an argument to some function. Your controller might look something like this:
class Shortener extends CI_Controller {
private function shorten( $token ){
// Find the URL that belongs to the token and redirect
}
public function _remap( $method, $params = array() ) {
// Catch other controller methods, pulled from the CodeIgniter docs
if ( method_exists( $this, $method ) ) {
return call_user_func_array( array( $this, $method ), $params );
}
$this->shorten( $method );
}
}

Resources