I have a simple URL rewriting setup with a .htaccess file. Excerpt:
RewriteEngine On
RewriteRule ^home(/)?$ index.php?mod=frontpage&com=showFrontpage
RewriteRule ^signup(/)?$ index.php?mod=usermanager&com=showRegistrationForm
This works perfectly fine. However, so does a request on the old style URL. When such a request comes in, I want to perform a 301 Permanent Redirect to the SEO friendly URL, however I cannot seem to figure out how I would map /index.php?mod=frontpage&com=showFrontpage to /home. Would I have to parse the .htaccess file and do some Regex hacking for this?
The URL rewriting was introduced pretty late into the project so the PHP script isn't 'aware' of the URL rewriting that's taking place; the .htaccess file is the only place this data is saved...
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/index.php$
RewriteCond %{QUERY_STRING} ^id=(.*)$
RewriteRule ^(.*)$ /home/%1? [R=302]
example.com/index.php?id=uri will redirect to: example.com/home/uri
You can accomplish this in two ways:
via .htaccess
via phpcode
In either ways, be sure to not fall into a rediretion loop.
Via .htaccess
Use RewriteCond to check the QUERY_STRING and redirect depending on the querystring. Don't forget to add the [L] flag to prevent Apache to continue executing other rewrite rules and the R=301 flag to redirect the client.
Via php
Here you must distinguish between request from the client and requests from the server. You might want to change your rewrite rule and pass an additional parameter, example
RewriteRule ^home(/)?$ index.php?mod=frontpage&com=showFrontpage&server=1
Then, in your code, check whether the parameter exists and redirect if not.
In case anyone's interested, I solved this myself using this (probably absolutely horrible) piece of PHP code.
class clsURL {
static function checkURL() {
// don't allow requests on old style URL's
if (($_SERVER['SCRIPT_NAME'] . '?' . $_SERVER['QUERY_STRING']) == $_SERVER['REQUEST_URI'] &&
$_SERVER['REQUEST_METHOD'] != 'POST') {
// redirect to new style URL
$redirectTable = self::createReverseTable();
$currentURL = $_SERVER['REQUEST_URI'];
if (substr($currentURL, 0, 1) == "/")
$currentURL = substr($currentURL, 1);
$newURL = self::getReverseURL($currentURL, $redirectTable);
if ($newURL) {
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: /' . $newURL);
exit;
}
}
}
static function getReverseURL($current, $reverseTable) {
// filter out some common stuff
$current = preg_replace("/&mid=[0-9]+/", "", $current);
foreach ($reverseTable as $pair) {
if (preg_match("|" . $pair['from'] . "|", $current)) {
return preg_replace("|" . $pair['from'] . "|", $pair['to'], $current);
}
}
// nothing found
return false;
}
static function createReverseTable() {
$file = fopen('.htaccess', 'r');
$reverse = array();
while ($line = fgets($file)) {
if (stripos($line, 'RewriteRule') === 0) {
$parts = preg_split("/[\\s\\t]/", $line, 3, PREG_SPLIT_NO_EMPTY);
$regex = trim($parts[1]);
$url = trim($parts[2]);
$parts[2] = $url;
$matches = array();
if (preg_match_all("/\\$[0-9]/", $url, $matches)) {
$matches = $matches[0]; // why? don't know.
$from = str_replace('?', '\\?', $url);
$to = $regex;
foreach ($matches as $match) {
$index = substr($match, 1);
$bracket = 0;
for ($i = 0; $i < strlen($regex); ++$i) {
if (substr($regex, $i, 1) == "(") {
$bracket++;
if ($bracket == $index) {
$pattern = "";
$j = $i + 1;
while (substr($regex, $j, 1) != ")") {
$pattern .= substr($regex, $j, 1);
$j++;
}
$from = str_replace('$' . $index, '(' . $pattern . ')', $from);
$to = preg_replace('/\\(' . preg_quote($pattern, '/') . '\\)/', '\\$' . $index, $to, 1);
}
}
}
}
// remove optional stuff that we don't use
$to = str_replace('(-(.*))?', '', $to);
// remove ^ and (/)?$
$to = substr($to, 1);
if (substr($to, -5) == '(/)?$')
$to = substr($to, 0, strlen($to) - 5);
$from = '^' . $from . '$';
// index.php is optional
$from = str_replace('index.php', '(?:index\\.php)?', $from);
$reverse[] = array(
'from' => $from,
'to' => $to
);
} else {
$from = str_replace('?', '\\?', $url);
$to = $regex;
// remove ^ and (/)?$
$to = substr($to, 1);
if (substr($to, -5) == '(/)?$')
$to = substr($to, 0, strlen($to) - 5);
$from = '^' . $from . '$';
// index.php is optional
$from = str_replace('index.php', '(?:index\\.php)?', $from);
$reverse[] = array(
'from' => $from,
'to' => $to
);
}
}
}
fclose($file);
return $reverse;
}
}
Related
Say if I defined a route GET /user/{user_id}/post/{post_id}. How do I get the un-substitute route in middleware? i.e. if the request is GET /usr/123/post/456, is there a pre-defined function that can get me /user/{user_id}/post/{post_id}?
I am currently using following snippet
$urlParam = $request->route()[2];
if (isset($urlParam) && count($urlParam)) {
$urlPath = substr(str_replace(
array_map(function($item) { return "/" . $item . "/"; }, array_values($urlParam)),
array_map(function($item) { return "/{" . $item . "}/"; }, array_keys($urlParam)),
"/" . $request->path() . "/"), 1, -1);
}
return $urlPath;
but as you can see this is not bug-free, if both user_id & post_id are the same, above snippet will not generate right result.
In Laravel
If you wan to get the same route URI you can use
$request->route()->uri();
This will return user/{user_id}/post/{post_id}
In Lumen
$segments = $request->segments();
foreach ($request->route()[2] as $parameter => $value) {
$segment_index = array_search($value, $request->segments());
$segments[$segment_index] = "{{$parameter}}";
}
$segments = implode('/', $segments);
dd($segments);
And the result will be user/{user_id}/post/{post_id}
I have this code below which generates a query string for my url.
Question I would like to know is there away that it could automatically replace the first & with a ? question mark no matter what the first $_GET is.
$url = '';
if ($this->input->get('directory')) {
$pos = strrpos($this->input->get('directory'), '/');
if ($pos) {
$url .= '&directory=' . urlencode(substr($this->input->get('directory'), 0, $pos));
}
}
if ($this->input->get('target')) {
$url .= '&target=' . $this->input->get('target');
}
if ($this->input->get('thumb')) {
$url .= '&thumb=' . $this->input->get('thumb');
}
$data['parent'] = base_url('image_manager' . $url);
Found solution
$find = '&';
$replace = '?';
$result = preg_replace("/$find/", $replace, $url, 1);
echo $result;
I have build my own component in joomla and client wants now a friendly urls f.e
website.com/someplace/{product-id}-{product-name}. So i Build my own router like this.
function componentBuildRoute(&$query)
{
$segments = [];
if (isset($query['view'])) {
$segments[] = "szkolenie";
unset($query['view']);
}
if (isset($query['product_id'])) {
$productName = JFilterOutput::stringURLSafe(strtolower(getProductName($query['product_id'])));
$newName = $query['product_id'] . '-' . $productName;
$segments[] = $newName;
unset($query['product_id']);
}
return $segments;
}
and parse route function
function componentParseRoute($segments)
{
$app = JFactory::getApplication();
$menu = $app->getMenu();
$item =& $menu->getActive();
$count = count($segments);
switch ($item->query['view']) {
case 'catalogue' : {
$view = 'training';
$id = $segments[1];
}
break;
}
$data = [
'view' => $view,
'product_id' => $id
];
return $data;
}
While on the end of buildroute function segments are ok I have exactly what I want that on the beginning of parse route I have something like
website.com/szkolenie/1-krakow <-- I dont know wtf is this krakow( I know it is city i Poland) but still where is it get from ? The getProductName function implementation is
function getProductName($productId)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('#__component_training.id as id, #__component_product' . name)
->from($db->quoteName('#__component_training'))
->where('#__s4edu_product.product_id = ' . $productId)
->leftJoin('#__component_product ON
#__component_training.product_id=#__component_product.product_id');
$training = $db->loadObject();
return trim($training->name);
}
So taking all this into consideration I think that something is happening between the buildRoute and parseRoute, something what filters the $segment[1] variable, but how to disable that and why is it happening ?
P.S
Please do not send me to https://docs.joomla.org/Joomla_Routes_%26_SEF
I already know all the tutorials on joomla website which contains anything with sef.
P.S.S
It is built on joomla 3.7.0
You do not have a product named "krakow" ?
If not you can try to remove the $productName from the build function, just to check if this "krakow" is added automaticaly or it's from the getProductName() function.
Also i noticed that you have an error i guess in the function getProductName()
->where('#__s4edu_product.product_id = ' . $productId)
It's should be
->where('#__component_product.product_id = ' . $productId)
i have problem with codeigniter 3 , the project work fine in localhost , but when i upload my project in host , i see
404 Page Not Found
The page you requested was not found.
i remove .httaccess file , remove all of my routes , but dont work.
i have two controller :
class test extends CI_Controller {}
class testen extends CI_Controller {}
my htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine On
# !IMPORTANT! Set your RewriteBase here and don't forget trailing and leading
# slashes.
# If your page resides at
# http://www.example.com/mypage/test1
# then use
# RewriteBase /mypage/test1/
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule .* http://%1%{REQUEST_URI} [R=301,L]
</IfModule>
<IfModule !mod_rewrite.c>
# If we don't have mod_rewrite installed, all 404's
# can be sent to index.php, and everything works as normal.
# Submitted by: ElliotHaughin
ErrorDocument 404 /index.php
</IfModule>
edit:
my routes:
$route['default_controller'] = 'isogamsharghedonya';
$route['404_override'] = '';
$route['translate_uri_dashes'] = FALSE;
$route["en"] = "isogamsharghedonyaen";
$route["fa"] = "isogamsharghedonya";
$route["en"] = "isogamsharghedonyaen/index";
$route["en/isogam-sharghe-donya-service"] = "isogamsharghedonyaen/service";
$route["en/isogam-sharghe-donya-news"] = "isogamsharghedonyaen/news";
$route["en/isogam-sharghe-donya-tvc"] = "isogamsharghedonyaen/video";
$route["en/isogam-sharghe-donya-certificate"] = "isogamsharghedonyaen/certificate";
$route["en/isogam-sharghe-donya-honor"] = "isogamsharghedonyaen/honor";
$route["en/isogam-sharghe-donya-ceo"] = "isogamsharghedonyaen/aboutCeo";
$route["en/isogam-sharghe-donya-about-company"] = "isogamsharghedonyaen/aboutCompany";
$route["en/isogam-sharghe-donya-team"] = "isogamsharghedonyaen/aboutTeam";
$route["en/isogam-sharghe-donya-contact"] = "isogamsharghedonyaen/contact";
$route["en/send-message"] = "isogamsharghedonyaen/sendMail";
$route["en/insulation-orders"] = "isogamsharghedonyaen/order";
$route["en/new-insulation-orders"] = "isogamsharghedonyaen/newOrder";
$route["fa"] = "isogamsharghedonya/index";
$route["fa/" . rawurlencode("خدمات-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/service";
$route["fa/" . rawurlencode("اخبار-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/news";
$route["fa/" . rawurlencode("تیزر-های-تبلیغاتی-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/video";
$route["fa/" . rawurlencode("گواهینامه-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/certificate";
$route["fa/" . rawurlencode("افتخارات-و-جوایز-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/honor";
$route["fa/" . rawurlencode("مدیر-عامل-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/aboutCeo";
$route["fa/" . rawurlencode("درباره-شرکت-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/aboutCompany";
$route["fa/" . rawurlencode("تیم-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/aboutTeam";
$route["fa/" . rawurlencode("تماس-با-ایزوگام-شرق-دنیا")] = "isogamsharghedonya/contact";
$route["fa/" . rawurlencode("ارسال-پیام")] = "isogamsharghedonya/sendMail";
$route["fa/" . rawurlencode("سفارش-ایزوگام")] = "isogamsharghedonya/order";
$route["fa/" . rawurlencode("سفارش-جدید-ایزوگام")] = "isogamsharghedonya/newOrder";
require_once (BASEPATH . 'database/DB' . EXT);
require_once (BASEPATH . 'helpers/url_helper' . EXT);
require_once (BASEPATH . 'helpers/text_helper' . EXT);
$db = &DB();
$query = $db -> get('news');
$result = $query -> result();
foreach ($result as $row) {
$string = rawurlencode(str_replace(' ', '-', strtolower($row -> subjectFA)));
$route["fa/news/" . $string] = "isogamsharghedonya/newsDetails/$row->id";
}
$query = $db -> get('news');
$result = $query -> result();
foreach ($result as $row) {
$string = rawurlencode(str_replace(' ', '-', strtolower($row -> subjectEN)));
$route["en/news/" . $string] = "isogamsharghedonyaen/newsDetails/$row->id";
}
$query = $db -> get('product');
$result = $query -> result();
foreach ($result as $row) {
$string = rawurlencode(str_replace(' ', '-', strtolower($row -> nameFA)));
$route["fa/product/" . $string] = "isogamsharghedonya/productDetails/$row->id";
}
$query = $db -> get('product');
$result = $query -> result();
foreach ($result as $row) {
$string = rawurlencode(str_replace(' ', '-', strtolower($row -> nameEN)));
$route["en/product/" . $string] = "isogamsharghedonyaen/productDetails/$row->id";
}
$query = $db -> get('trailer');
$result = $query -> result();
foreach ($result as $row) {
$string = rawurlencode(str_replace(' ', '-', strtolower($row -> nameFA)));
$route["fa/video/" . $string] = "isogamsharghedonya/videoDetails/$row->id";
}
$query = $db -> get('trailer');
$result = $query -> result();
foreach ($result as $row) {
$string = rawurlencode(str_replace(' ', '-', strtolower($row -> nameEN)));
$route["en/video/" . $string] = "isogamsharghedonyaen/videoDetails/$row->id";
}
Your controller and model files must begin with a capital letter.
An example: controllers/Index.php, models/Index_model.php
code in CI 3 core for controllers load (/system/core/router.php):
protected function _set_default_controller()
{
//... blah-blah-blah ...
if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php'))
{
// This will trigger 404 later
return;
}
//...blah-blah-blah...
}
It work in localhost, because you system is Windows. Unix like systems is case sensitive in work with files.
As i reviewed your code the first thing that you have rectify is that the way you have declare your controller since it is a good practice to define your controller as class Test extends CI_Controller instead of class test extends CI_Controller as you have declared some time it might create error and the second thing is that you have to check your .htaccess file is uploaded to your root directory of the project and as well as you also check in your routes file whether you have written the appropriate routing rule for your declared controller as well as the is the method is present in your class which is defined in your routes for the same
Here, I see someone suggesting to extend the Zend\View\Helper\Escaper\AbstractHelper;, resulting in something like this:
namespace Photo\View\Helper;
use Zend\View\Helper\Escaper\AbstractHelper;
class Imghelper extends AbstractHelper
{
protected $_baseUrl = null;
protected $_exists = array();
public function __construct ()
{
$url = PUBLIC_PATH;
$root = '/' . trim($url, '/');
if ($root == "/")
{$root = "";}
$this->_baseUrl = $root . "/";
}
public function escape($value)
{
return $this->getEscaper()->escapeHtml($value);
}
public function __invoke($path, $params = array())
{
$plist = array();
$str = null;
$imgpath = $this->_baseUrl . ltrim($path);
if (!isset($this->_exists[$path]))
{$this->_exists[$path] = file_exists(realpath($imgpath));}
if (!isset($params['alt']))
{$params['alt'] = '';}
foreach ($params as $param => $value)
{$plist[] = $param . '="' . $this->escape($value) . '"';}
$str = " ".join(" ", $plist);
$p = ($this->_exists[$path]) ? $this->_baseUrl.ltrim($path,'/') : null;
if (isset($p))
{return '<img src="'.$p.'" '.$str.' />';}
}
}
However, when I try it in my codes, I get an Error
Strict Standards: Declaration of Application\View\Helper\Imghelper::__invoke() should be compatible with Zend\View\Helper\Escaper\AbstractHelper::__invoke($value, $recurse = 0) in ...
Is it ok to error the error message? Or is there any better ways to do this? Thanks!
I wouldn't recommend extending the Abstract Escape helper since you aren't writing an escape helper. Stick to your original plan and just extend Zend\View\Helper\AbstractHelper. You can then access the escape helpers via. $this->view->escapeHtml(), $this->view->escapeJs() and so on.