Zend Framework - Redirects - php

Running ZF + xampp on localhost (I'm new to this)..
I have this code:
$url = $this->getRequest()->getRequestUri();
...
$session->requestURL = $url;
& var_dump shows $url=
/kakool/public/admin/catalog/item/update/1
But later, in this code:
if (isset($session->requestURL)) {
$url = $session->requestURL; }
# again, var_dump shows $url=/kakool/public/admin/catalog/item/update/1
$this->_redirect($url);
It's redirecting to this url:
/kakool/public/kakool/public/admin/catalog/item/update/1
Annoying... Anyone have any ideas?

The _redirect method defaults to assuming you're giving it a path relative to the root of the current app - so even if you pass a URL starting with /, it'll append the base path to the front of it.
You have two options:
1/ Give it a path relative to the project like it wants:
$url = $this->getRequest()->getPathInfo();
# var_dump now shows $url=/admin/catalog/item/update/1
$this->_redirect($url);
2/ Pass an extra flag that tells the _redirect not to add the base path:
$this->_redirect($url, array('prependBase' => false));

I think that you have to replace this :
$url = $this->getRequest()->getRequestUri();
...
$session->requestURL = $url;
with this :
$url = $this->getRequest()->getRequestUri();
...
if(!isset($session->requestURL)){
$session->requestURL = $url;
}

Related

Laravel function to convert a realpath() to an absolute URL

I have declared a path pointing to a folder like this:
$path = realpath(public_path('uploads'));
This gives me that value: /var/www/mywebsite/public/uploads
Now, I want to turn this into an absolute URL, like this: http://www.mywebsite.com/uploads
Here is what I did:
dd(asset($path)); // Wrong: http://www.mywebsite.com/var/www/mywebsite/public/uploads
dd(url($path); // Same.
dd(asset('uploads')); // Right, but I only want to use $path
Is there a pre-built way to achieve this in Laravel 5?
You were almost there with asset($path).
Just amend this to asset('uploads') and this will resolve to http://www.mywebsite.com/uploads.
The asset URL helper generates a URL to the public folder of your Laravel application. You then just add the folder you want to go to from there.
Yours $path is taken relatively to public folder with public_path('uploads'), so, 'uploads' by itself points to absolute path. Just add host part to it. Like:
$inPublic = 'uploads';
$localPath = realpath(public_path($inPublic));
// then, either
$url = url("/" . trim($inPublic, "/\\"));
// or
$publicPath = realpath(public_path());
$relativePart = str_replace($publicPath, '', $localPath);
$url = url("/" . trim($relativePart, "/\\"));

Codeigniter routes not working, possibly because of internationalization?

Working on codeigniter project.
Got stuck with routes.
I want to access en/company/login through en/login, so how do I define routes then?
Right now routes code looks like this:
// URI like '/en/about' -> use controller 'about'
$route['^(en|lv)/(.+)$'] = "$2";
// '/en', '/lv' URIs -> use default controller
$route['^(en|lv)$'] = $route['default_controller'];
$route['company/login'] = "login";
tried:
$route['^(en|lv)/company/login'] = "login";
Obviously, Im not getting something.
Can you help please?
Your problem is (i had the same) that this:
$route['^(en|lv)/(.+)$'] = "$2";
overrides your rule for:
$route['^(en|lv)/company/login'] = "login";
Try this:
$route['^(en|lv)\/(company)\/(.+)$'] = "login";
Maybe it should help you to override the first pattern
And if not, edit the first pattern to this:
$route['^(en|lv)\/(?!company).+$'] = "$2";
$route["(en|fr|gr)/(:any)/login"] = "login/index/$1";
--
public function index($company)
{
$language = strtolower($this->uri->rsegments[3]);
if(!in_array($language, ['en', 'fr'])){
// set a default language
// if the route does not provide a valid one
$language = 'en';
}
// Load the language file for the selected language
// for example english, language/en/en_lang.php
$this->lang->load($language, $language);
}
Thank you for your answer, but it seems that I didnt explain that
/company/ is controller and /login/ is "company" function. Your
solution wont work for me. :/
// The $route should contain the uri,
// you seem to have them mixed up.
// $route['uri'] = "controller/method"
$route['(en|lv)/login'] = 'company/login';

How to get the original URI extension using PHP Tonic?

I'm developing a REST API using PHP and Tonic. The framework has a fine feature which is the inference of the Content-Type based on the extension of the URI requested.
In the case of the service I'm developing, it's important to know the full name of the requested file.
If I use the following code:
$this->request->uri;
For a URI such as http://service.com/image1.jpg, all I get is image1.
I could get the information I need going straight through $_SERVER['REQUEST_URI'], but I'd like to use the facilities of the framework for this (should there be any).
Also, I found the documentation pretty poor, so, any doc links will be appretiated as well. Thanks.
You should take a look here:
private function getURIFromEnvironment($options)
{
$uri = $this->getOption($options, 'uri');
if (!$uri) { // use given URI in config options
if (isset($_SERVER['REDIRECT_URL']) && isset($_SERVER['SCRIPT_NAME'])) { // use redirection URL from Apache environment
$dirname = dirname($_SERVER['SCRIPT_NAME']);
$uri = substr($_SERVER['REDIRECT_URL'], strlen($dirname == DIRECTORY_SEPARATOR ? '' : $dirname));
} elseif (isset($_SERVER['REQUEST_URI'])) { // use request URI from environment
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
} elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) { // use PHP_SELF from Apache environment
$uri = substr($_SERVER['PHP_SELF'], strlen($_SERVER['SCRIPT_NAME']));
} else { // fail
throw new \Exception('URI not provided');
}
}
Specifically:
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
I would just dump $_SERVER and see whats available to you and replace or add with your need.

How to get baseUrl in ZF2 controller?

In my zf2 controller I want to retrieve the application base URL (for example http://example.com).
I tried the following call but it returns an empty string.
$this->request->getBasePath();
How can I then get the http://example.com part of URL in my controller?
I know this is not the prettiest way of doing it but, hey, it works:
public function indexAction()
{
$uri = $this->getRequest()->getUri();
$scheme = $uri->getScheme();
$host = $uri->getHost();
$base = sprintf('%s://%s', $scheme, $host);
// $base would be http://example.com
}
Or if you don't mind shortening everything you could do it in two lines:
public function indexAction()
{
$uri = $this->getRequest()->getUri();
$base = sprintf('%s://%s', $uri->getScheme(), $uri->getHost());
}
I'm not sure if there's a native way but you can use the Uri instance from Request.
You can take this snippet as a workaround until you've found a better solution:
$basePath = $this->getRequest()->getBasePath();
$uri = new \Zend\Uri\Uri($this->getRequest()->getUri());
$uri->setPath($basePath);
$uri->setQuery(array());
$uri->setFragment('');
$baseUrl = $uri->getScheme() . '://' . $uri->getHost() . '/' . $uri->getPath();
This works in the controller context. Note that in line 2, the Uri instance from the request is cloned in order not to modify the request's uri instance directly (to avoid side-effects).
I'm not happy with this solution but at least, it is one.
// Edit: Forgot to add the path, fixed!

Manage URL routes in own php framework

I'm creating a PHP Framework and I have some doubts...
The framework takes the url in this way:
http:/web.com/site/index
It takes the first parameter to load controller (site) and then loads the specific action (index).
If you've installed the framework in a base URL works ok, but if you install it in a subfolder like this:
http://web.com/mysubfolder/controller/action
My script parses it as controller = mysubfolder and action = controller.
If you have more subfolders the results will be worst.
This is my Route code:
Class Route
{
private $_htaccess = TRUE;
private $_suffix = ".jsp";
public function params()
{
$url='';
//nombre del directorio actual del script ejecutandose.
//basename(dirname($_SERVER['SCRIPT_FILENAME']));
if($this->_htaccess !== FALSE):
//no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
// muestra el "subdir" como primer parámetro
$url = $_SERVER['REQUEST_URI'];
if(isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])):
$url = str_replace("?" . $_SERVER['QUERY_STRING'], '',$url);
endif;
else:
if(isset($_SERVER['PATH_INFO'])):
$url = $_SERVER['PATH_INFO'];
endif;
endif;
$url = explode('/',preg_replace('/^(\/)/','',$url));
var_dump($url);
var_dump($_GET);
}
}
Thanks for any help you can give.
You are missing a base path. The routing script must now where to start when detecting a pattern or route detected.
Pseudo code:
//set the base URI
$base_uri = '/base';
//remove the base URI from the original uri. You can also REGEX or string match against it if you want
$route_uri = str_replace($base_uri,'',$uri);
//perform route matching $route_uri, in your code a simple explode
$url = explode('/',preg_replace('/^(\/)/','',$route_uri));
You can use this with or without RewriteBase for your .htaccess so long as they use the same harness - index.php.
Additionally, you can improve your route match procedure using Regular Expressions function like preg_match and preg_match_all. They let you define a pattern to match against and results to an array of matching strings - see http://php.net/manual/en/function.preg-match.php.
Even if you are creating your own framework, there is no reason not to reuse robust, well tested and documented components, like this Routing component.
Just use Composer, which has become the standard for dependency management in PHP, and you'll be fine. Add as many components as you want to your stack.
And here you have a must read guide on how to make your own framework.
Yes, I think I know how to fix that.
(Disclaimer: I know that you know most of this but I am going to explain everything for others who may not know some of the gotchas)
Using PATH_INFO and .htaccess
There is a trick in php where if you go to a path like:
http://web.com/mysubfolder/index.php/controller/action
you will get "/controller/action" in the $_SERVER['PATH_INFO'] variable
Now what you need to do is take a .htaccess file (or equivalent) and make it tell your php script the current folder depth.
To do this, put the .htaccess file into the "mysubfolder"
mysubfolder
.htaccess
index.php
.htaccess should contain:
RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule (.*) index.php/$1
(I used the yii framework manual as reference, I also recommend using the html5 boilerplate)
Basically you set it up to redirect everything to index.php at a specific point in the url.
Now if you visit: http://web.com/mysubfolder/index.php/controller/action
Now you can get the right path "/controller/action" from $_SERVER['PATH_INFO']
Except it's not going to have any value if you visit http://web.com/mysubfolder/ because the .htaccess file will ignore the rewrite because the http://web.com/mysubfolder/ path requests the mysubfolder/index.php which actually exists and gets denied thank yo RewriteCond %{REQUEST_FILENAME} !-f.
ifsetor function
For this you can use this super handy function called ifsetor (I don't remember where I got it)
function ifsetor(&$variable, $default = null) {
return isset($variable)? $variable: $default;
}
What it does is take a reference to a variable that might or might not exist and provide a default if it does not exist without throwing any notices or errors
Now you can use it to take the PATH_INFO variable safely like so
In your index.php
function ifsetor(&$variable, $default = null) {
return isset($variable)? $variable: $default;
}
$path = ifsetor($_SERVER['PATH_INFO'],'/');
var_dump($path);
php 5.4 also has this new shorter ternary format which you can use if you don't care about notices (I do)
$path = $_SERVER['PATH_INFO']?:'/';
Handling the QUERY_STRING
Now tecnically you are not getting a URL, it is merely its path part and will not contain the query_string, for example when visiting
http://web.com/mysubfolder/index.php/test?param=val
you will only get '/test' in the $path variable, to get the query string use the $_SERVER['QUERY_STRING'] variable
index.php
function ifsetor(&$variable, $default = null) {
return isset($variable)? $variable: $default;
}
$path = ifsetor($_SERVER['PATH_INFO'],'/');
$fullpath = ($_SERVER['QUERY_STRING'])? $path.'?'.$_SERVER['QUERY_STRING']:$path;
var_dump($fullpath);
But that might depend on your needs
$_SERVER['QUERY_STRING'] vs $_GET
Also keep in mind that the $_SERVER['QUERY_STRING'] variable is different from the $_GET and $_REQUEST variables because it keeps duplicate parameters from the query string, for example:
Visiting this page
http://web.com/mysubfolder/controller/action?foo=1&foo=2&foo=3
if going to give you a $_SERVER['QUERY_STRING'] that looks like
?foo=1&foo=2&foo=3
While the $_GET variable is going to be an array like this:
array(
'foo'=>'3'
);
If you don't have .htaccess
You can try using the SCRIPT_NAME to your advantage
list($url) = explode('?',$_SERVER['REQUEST_URI']);
list($basepath) = explode('index.php',$_SERVER['SCRIPT_NAME']);
$url = substr($url,strlen($basepath));
If you like to blow up stuff like me :)
Your case
Class Route
{
private $_htaccess = TRUE;
private $_suffix = ".jsp";
public function params()
{
$url='';
//nombre del directorio actual del script ejecutandose.
//basename(dirname($_SERVER['SCRIPT_FILENAME']));
if($this->_htaccess !== FALSE):
//no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
// muestra el "subdir" como primer parámetro
list($url) = explode('?',$_SERVER['REQUEST_URI']);
$basepath = dirname($_SERVER['SCRIPT_NAME']);
$basepath = ($basepath==='/')? $basepath: $basepath.'/';
$url = substr($url,strlen($basepath));
else:
if(isset($_SERVER['PATH_INFO'])):
$url = $_SERVER['PATH_INFO'];
$url = preg_replace('|^/|','',$url);
endif;
endif;
$url = explode('/',$url);
var_dump($url);
var_dump($_GET);
}
}
I hope this helps
P.S. Sorry for the late reply :(
At some point you will have to check the $_SERVER ['HTTP_HOST'] and a config var defined by the programmer/user wich indicates the subfolder(s) where the app is located, and remove the portion you are not interested in from the rest of the URL.
You can check this forum post on the codeigniter formus for some hints.
CodeIgniter uses another different way to route the controller/method internally.
You do the routing by the $_SERVER['PATH_INFO'] value. You use the urls like this: myapp.com/index.php/controller/method .
To avoid showing index.php on the uri you must rely on an Apache rewrite rule, but even with that I think that the CI one is a nice solution, once you have your index file location, you can avoid all the hassle of parsing the URL.
If I am understanding what you are after correctly, then one solution may be to carry on doing what you are doing, but also get the path of the main routing script (using realpath() for example).
If the last folder (or folder before that etc) matches the beginning URL item (or another section), you ignore it and go for the next one.
Just my 2 cents :-).
Within the application configuration script place a variable which will be set to the path the application runs at.
An alternative is to dynamically set that path.
Before the part
$url = explode('/',preg_replace('/^(\/)/','',$url));
strip the location (sub-folder) path out of the $url string using the predefined application path.
This is how i implemented loader.php
<?php
/*#author arun ak
auto load controller class and function from url*/
class loader
{
private $request;
private $className;
private $funcName;
function __construct($folder = array())
{
$parse_res = parse_url($this->createUrl());
if(!empty($folder) && trim($folder['path'],DIRECTORY_SEPARATOR)!='')
{
$temp_path = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
$folder_path = explode(DIRECTORY_SEPARATOR,trim($folder['path'],DIRECTORY_SEPARATOR));
$temp_path = array_diff($temp_path,$folder_path);
if(empty($temp_path))
{
$temp_path = '';
}
}else
{
if(trim($parse_res['path'],DIRECTORY_SEPARATOR)!='')
{
$temp_path = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
}
else
$temp_path ='';
}
if(is_array($temp_path))
{
if(count($temp_path) ==1)
{
array_push($temp_path,'index');
}
foreach($temp_path as $pathname)
{
$this->request .= $pathname.':';
}
}
else $this->request = 'index'.':'.'index';
}
private function createUrl()
{
$pageURL = (#$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
return $pageURL;
}
public function autolLoad()
{
if($this->request)
{
$parsedPath = explode(':',rtrim($this->request,':'));
if(is_file(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php'))
{
include_once(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php');
if(class_exists($parsedPath[0].'_controller'))
{
$class = $parsedPath[0].'_controller';
$obj = new $class();
//$config = new config('localhost','Winkstore','nCdyQyEdqDbBFpay','mawinkcms');
//$connect = connectdb::getinstance();
//$connect->setConfig($config);
//$connection_obj = $connect->connect();
//$db = $connect->getconnection();//mysql link object
//$obj->setDb($db);
$method = $parsedPath[1];
if(method_exists ($obj ,$parsedPath[1] ))
{
$obj->$method();
}else die('class method '.$method.' not defined');
}else die('class '.$parsedPath[0]. ' has not been defined' );
} else die('controller not found plz define one b4 u proceed'.APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'.php');
}else{ die('oops request not set,i know tis is not the correct way to error :)'); }
}
}
Now in my index file
//include_once('config.php');
include_once('connectdb.php');
require_once('../../../includes/db_connect.php');
include_once('view.php');
include_once('abstractController.php');
include_once('controller.php');
include_once('loader.php');
$loader = new loader(array('path'=>DIRECTORY_SEPARATOR.'magsonwink'.DIRECTORY_SEPARATOR.'modules'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'atom'.DIRECTORY_SEPARATOR));
$loader->autolLoad();
I haven't used the concept of modules.only controller action and view are rendered.
Are you sure you have your htaccess correctly?
I guess if you're placing your framework on subfolder, then you have to change your RewriteBase in htaccess file from / to /subfolder/. it would be something like this:
# on root
RewriteBase /
#on subfolder
RewriteBase /subfolder/
that's only thing I could wonder of that in your case ...
I don't use OOP, but could show you some snippets of how I do things to dynamically detect if I'm in a subdirectory. Too keep it short and to the point I'll only describe parts of it instead of posting all the code.
So I start out with a .htaccess that send every request to redirect.php in which I splice up the $_SERVER['REQUEST_URI'] variable. I use regex to decide what parts should be keys and what should be values (I do this by assigning anything beginning with 0-9 as a value, and anything beginning with a-z as key) and build the array $GET[].
I then check the path to redirect.php and compare that to my $GET array, to decide where the actual URL begins - or in your case, which key is the controller. Would look something like this for you:
$controller = keyname($GET, count(explode('/', dirname($_SERVER['SCRIPT_NAME']))));
And that's it, I have the first part of the URL. The keyname() function looks like this:
/*************************************
* get key name from array position
*************************************/
function keyname ($arr, $pos)
{
$pos--;
if ( ($pos < 0) || ( $pos >= count($arr) ) )
return ""; // set this any way you like
reset($arr);
for($i = 0;$i < $pos; $i++) next($arr);
return key($arr);
}
To get the links pointing right I use a function called fixpath() like this:
print 'link';
And this is how that function looks:
/*************************************
* relative to absolute path
*************************************/
function fixpath ($path)
{
$root = dirname($_SERVER['SCRIPT_NAME']);
if ($root == "\\" || $root == ".") {
$root = "";
}
$newpath = explode('/', $path);
$newpath[0] .= $root;
return implode('/', $newpath);
}
I hope that helps and can give you some inspiration.
Forget about "reinventing the wheel is wrong" claims. They don't have to use our wheels. I walked on the same road a while ago and i'm totally grateful what i get... i hope you will too
When it comes to the answer to your specific problem -which if faced too- there is a very easy solution. it's a new line in .htaccess at root folder...
Just add line below to your root .htaccess file ; (if your subfoler is "subfolder" )
RewriteRule subfolder/ - [L]
This will leave apart this folder from rewriting directives
By using this way you can install as many instances of your framework as you wish. But if you want this to be framework driven then you have to create/change .htaccess within your framework.
Create /myBaseDirectory/public directory and put your files there - like index.php.
This works because Apache sees this directory like base directory.
basically grab the url string after your first slash, and then explode it into an array (i use '/' as a delimiter).
then carefully array_shift off your elements and store them as variables
item 0: controller
item 1: the action / method in that controller
item 2 thru n: the remaining array is your params

Categories