How to get category selector in system configuration in magento 2?
I need to get all levels of categories in the admin configuration section as multi select option. I have added the following code and I am getting desired result. But I want to do it using recursive function . Please help me to do the same.
namespace Vendor\Productslider\Model\Config\Source;
use Magento\Framework\Option\ArrayInterface;
use Magento\Catalog\Helper\Category;
class Categorylist implements ArrayInterface
{
protected $_categoryHelper;
protected $categoryRepository;
public function __construct(
\Magento\Catalog\Helper\Category $catalogCategory,
\Magento\Catalog\Model\CategoryRepository $categoryRepository
)
{
$this->_categoryHelper = $catalogCategory;
$this->categoryRepository = $categoryRepository;
}
/*
* Return categories helper
*/
public function getStoreCategories($sorted = false, $asCollection = false, $toLoad = true)
{
return $this->_categoryHelper->getStoreCategories($sorted , $asCollection, $toLoad);
}
/*
* Option getter
* #return array
*/
public function toOptionArray()
{
$arr = $this->toArray();
$ret = [];
foreach ($arr as $key => $value)
{
$ret[] = [
'value' => $key,
'label' => $value
];
}
return $ret;
}
/*
* Get options in "key-value" format
* #return array
*/
public function toArray()
{
$categories = $this->getStoreCategories(true,false,true);
$categoryList = $this->renderCategories($categories);
return $categoryList;
}
public function renderCategories($_categories)
{
$categoryList = array();
foreach ($_categories as $category){
$categoryList[$category->getEntityId()] = __($category->getName()); // Main categories
$categoryObj = $this->categoryRepository->get($category->getId());
$subcategories = $categoryObj->getChildrenCategories();
foreach($subcategories as $subcategory) {
$categoryList[$subcategory->getEntityId()] = __('--'.$subcategory->getName()); // 1st level Sub categories
if($subcategory->hasChildren()) {
$childCategoryObj = $this->categoryRepository->get($subcategory->getId());
$childSubcategories = $childCategoryObj->getChildrenCategories();
foreach($childSubcategories as $childSubcategory) {
$categoryList[$childSubcategory->getEntityId()] = __('----'.$childSubcategory->getName()); // 2nd level Sub categories
}
}
}
}
return $categoryList;
}
}
Thank God !!
I have find a solution
namespace Vendor\Productslider\Model\Config\Source;
use Magento\Framework\Option\ArrayInterface;
use Magento\Catalog\Helper\Category;
class Categorylist implements ArrayInterface
{
protected $_categoryHelper;
protected $categoryRepository;
protected $categoryList;
public function __construct(
\Magento\Catalog\Helper\Category $catalogCategory,
\Magento\Catalog\Model\CategoryRepository $categoryRepository
)
{
$this->_categoryHelper = $catalogCategory;
$this->categoryRepository = $categoryRepository;
}
/*
* Return categories helper
*/
public function getStoreCategories($sorted = false, $asCollection = false, $toLoad = true)
{
return $this->_categoryHelper->getStoreCategories($sorted , $asCollection, $toLoad);
}
/*
* Option getter
* #return array
*/
public function toOptionArray()
{
$arr = $this->toArray();
$ret = [];
foreach ($arr as $key => $value)
{
$ret[] = [
'value' => $key,
'label' => $value
];
}
return $ret;
}
/*
* Get options in "key-value" format
* #return array
*/
public function toArray()
{
$categories = $this->getStoreCategories(true,false,true);
$categoryList = $this->renderCategories($categories);
return $categoryList;
}
public function renderCategories($_categories)
{
foreach ($_categories as $category){
$i = 0;
$this->categoryList[$category->getEntityId()] = __($category->getName()); // Main categories
$list = $this->renderSubCat($category,$i);
}
return $this->categoryList;
}
public function renderSubCat($cat,$j){
$categoryObj = $this->categoryRepository->get($cat->getId());
$level = $categoryObj->getLevel();
$arrow = str_repeat("---", $level-1);
$subcategories = $categoryObj->getChildrenCategories();
foreach($subcategories as $subcategory) {
$this->categoryList[$subcategory->getEntityId()] = __($arrow.$subcategory->getName());
if($subcategory->hasChildren()) {
$this->renderSubCat($subcategory,$j);
}
}
return $this->categoryList;
}
}
Related
I'm trying to use a function that I wrote inside my routes.php file:
the function is this:
function userScore($uid) {
$db = $app->get('db');
//calcolo punteggio totale
$query_punti = $db->table('prodotti_sounding')
->where('id_utente', $uid)
->select('punti')
->get();
$totale_punti = 0;
foreach($query_punti as $item) {
$totale_punti += $item->punti;
}
}
it returns this error:
Slim Application Error The application could not run because of the
following error:
Type: Error Message: Call to a member function get() on null
where am I wrong?
EDIT
my relevant code in routes.php after the first answer is:
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
use Illuminate\Database\Connection;
use Slim\Http\UploadedFile;
use Illuminate\Support\Facades\DB as DB;
$container = $app->getContainer();
$app->post('/sendbarcode', function ($request, $response){
/* parametri barcode */
/** #var Container $this */
/** #var Connection $db */
$barcode = $request->getParsedBodyParam('barcode');
$id_utente = $request->getParsedBodyParam('id_utente');
$db = $this->get('db');
// prepare data for json
$array['itacheck'] = 0;
if(checkbarcode($barcode) == 1 ) {
$array['it_check'] = 1;
$array['punti'] = 25;
$array['totalepunti'] = userScore($id_utente);
}
$array['barcode'] = $rows;
if(count($rows) > 0){
return $response->withJson($array, 200, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_LINE_TERMINATORS);
}
});
function userScore($uid) {
//calcolo punteggio totale in base alle segnalazioni pregresse
$query_punti = DB::table('prodotti_sounding')
->where('id_utente', $uid)
->select('punti')
->get();
// check total points
$totale_punti = 0;
foreach($query_punti as $item) {
$totale_punti += $item->punti;
}
}
Error becomes $db = $app->get('db');, because you not defained $app variable. Instaed of you can use this
//calcolo punteggio totale
$query_punti = DB::table('prodotti_sounding')
->where('id_utente', $uid)
->select('punti')
->get();
DB full class name is \Illuminate\Support\Facades\DB
Edit
That case add $app attribute in function argument
function userScore($uid, $app) {
$db = $app->get('db');
I have a SQL query that return the result to List
public class WebTrafficStat
{
public string Group { get; set; }
public string Stat { get; set; }
public string Total { get; set; }
public bool? IsSubTotal { get; set; }
}
The result must be displayed as HTML Pivot table with either results grouped by "Stat" or "Group" field.
SQL result:
Desired result as HTML
I did the functions that does this PHP but now the project must be written in MVC Core
This is my PHP functions that I used currently
I grouped the array from SQL call results here:
function array_group_by(array $arr, $gElement, $gkey) {
$refined = $arr;
$result = array();
foreach ($arr[$gElement] as $data) {
$id = $data[$gkey];
if ( isset($data[$gkey]) && !empty($data[$gkey]) ) {
if (isset($result[$id])) {
$result[$id][] = $data;
} else {
$result[$id] = array($data);
}
}
}
if ( !empty($result) ) {
$refined[$gElement] = array();
foreach($result as $key=>$value) {
$refined[$gElement][] = array('name' => $key, 'childs' => $value);
}
$refined['grouped'] = 1;
}
return $refined;
}
And second function is
function grouped_array_to_html ($grouped, $groupField ){
$tableRows = array();
$columns = array();
$Row_Data = array();
if ( $grouped['grouped'] == 1 ){ // grouping found
$columns[] = 'Group';
// table columns/headers
foreach ($grouped['rows'] as $row) {
foreach ($row['childs'] as $child) {
if ( !in_array($child[$groupField], $columns ) ){
$columns[] = $child[$groupField];
}
}
}
//table rows
foreach ($grouped['rows'] as $a => $row) {
$tableRows[$a][] = $row['name'];
foreach ($row['childs'] as $c => $child) {
foreach ($columns as $x => $col){
if ( $col == $child[$groupField] )
{
$tableRows[$a][$x] = $child['total'];
break;
}
}
}
}
//Output Finale
foreach ( $tableRows as $b => $tr )
{
foreach ($columns as $c => $col) {
if ( !isset($tableRows[$b][$c]) )
$Row_Data[$b][$c] = '-';
else
$Row_Data[$b][$c] = $tableRows[$b][$c];
}
}
} else { // no grouping
foreach ($grouped['rows'] as $row) {
$Row_Data[] = $row;
}
}
$htmlOut = array(
'theaders' => $columns,
'trows' => $Row_Data
);
$grouped['rows']['html'] = $htmlOut;
return $grouped;
}
And I call PHP like this ... this gives me HTML table header rows and Body rows
In this case, I tell it to group by "Stat" column
$result = grouped_array_to_html( array_group_by($response, 'rows', 'group'), 'stat' );
So please how can I achieve same result using EF Core or Linq
I ended up approaching it like this:
if ((Model.WebReport != null) && Model.WebReport.Rows.Any())
{
var columns = Model.WebReport.Rows
.Select(c => (Model.GroupBy.Equals("Group") ? c.Stat : c.Group))
.Distinct()
.ToList();
columns.Insert(0, "Group");
var reportStat = Model.WebReport.Rows
.GroupBy(g => (Model.GroupBy.Equals("Group") ? g.Group : g.Stat))
.Select(x => new
{
Group = x.Key,
Stats = x.ToDictionary(y => (Model.GroupBy.Equals("Group") ? y.Stat : y.Group), y => y.Total)
});
Model.Columns = columns;
Model.ReportStats = reportStat.ToList();
}
How to make loading multiple images and making many-to-many relationships on a table of apartments?
I have a model Apartment:
public function getApartmentImages()
{
return $this->hasMany(ApartmentImages::className(), ['apartment_id' => 'id']);
}
public function getImages()
{
return $this->hasMany(Images::className(), ['id' => 'image_id'])
->via('apartmentImages');
}
Model Images:
public function getApartmentImages()
{
return $this->hasMany(ApartmentImages::className(), ['image_id' => 'id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getApartments()
{
return $this->hasMany(Apartment::className(), ['id' => 'apartment_id'])
->via('apartmentImages');
}
Model ApartmentImages
public function getImage()
{
return $this->hasOne(Images::className(), ['id' => 'image_id']);
}
public function getApartment()
{
return $this->hasOne(Apartment::className(), ['id' => 'apartment_id']);
}
The apartment has a main image (layout) and many others.
I managed to make the layout load:
public function actionCreate()
{
$model = new Apartment();
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
$layout = new Images();
$layout->imageFile = UploadedFile::getInstanceByName('layout');
if ($layout->upload()) {
$model->layout_id = $layout->id;
}
if ($model->validate()) {
if ($model->save()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(',', array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set('Location', Url::toRoute(['view', 'id' => $id], true));
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to create the object for unknown reason.');
}
}
return $model;
}
I filled the array with all the sent pictures, and in the loop I upload to the site, and using
//INSERT INTO `apartment_images` (`apartment_id`, `image_id`) VALUES (...)
$model->link('images', $images[0]);
I create an entry in the link table.
public function actionCreate()
{
$model = new Apartment();
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
$layout = new Images();
$layout->imageFile = UploadedFile::getInstanceByName('layout');
$layout->validate();
if ($layout->upload()) {
$model->layout_id = $layout->id;
}
$count = count(UploadedFile::getInstancesByName('images'));//Get the number of images
$images = [new Images()];//First image required
$images[0]->imageFile = UploadedFile::getInstanceByName('images[0]');
if(!$images[0]->validate()) return $images[0]->errors;//Check errors
if ($model->validate()){
if ($model->save()) {
if ($images[0]->upload()) {
$model->link('images',$images[0]);//Binding many to many
}
for($i = 1; $i < $count; $i++) {//Check the rest and repeat again
$images[$i] = new Images();
$images[$i]->imageFile = UploadedFile::getInstanceByName('images['.$i.']');
if ($images[$i]->upload()) {
$model->link('images',$images[$i]);
}
}
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(',', array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set('Location', Url::toRoute(['view', 'id' => $id], true));
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to create the object for unknown reason.');
}
}
else return $model->errors;
return $model;
}
I am having some "Trying to get property of non-object" issue with facebook sign up. The server returns errors related to access_token.
i have error form line 490 and 451. on line 451 i succeed to solve it but i ve still 2 errors from line 490.
the line was fixed by changing if ( $token->access_token ) by if ( $token['access_token'] )
I think the problem is due to codeigniter.
the line 490 is the following one:
private function _token_string()
{
return 'access_token='.$this->_get('token')->access_token;
}
Here is the entire code:
class Facebook_Lib extends CI_Config
{
private $_api_url;
private $_api_key;
private $_api_secret;
private $_errors = array();
private $_enable_debug = FALSE;
function __construct()
{
$this->_obj =$CI =& get_instance();
$this->_obj->load->library('session');
$this->_obj->load->helper('url');
$this->_obj->load->helper('facebook');
$fb_api_id = $CI->db->get_where('settings', array('code' => 'SITE_FB_API_ID'))->row()->string_value;
$fb_api_secret = $CI->db->get_where('settings', array('code' => 'SITE_FB_API_SECRET'))->row()->string_value;
$this->_api_url = $this->_obj->config->item('facebook_api_url');
$this->_api_key = $fb_api_id;
$this->_api_secret = $fb_api_secret;
$this->session = new facebookSession();
$this->connection = new facebookConnection();
}
public function logged_in()
{
return $this->session->logged_in();
}
public function login($scope = NULL)
{
return $this->session->login($scope);
}
public function login_url($scope = NULL)
{
return $this->session->login_url($scope);
}
public function logout()
{
return $this->session->logout();
}
public function user()
{
return $this->session->get();
}
public function call($method, $uri, $data = array())
{
$response = FALSE;
try
{
switch ( $method )
{
case 'get':
$response = $this->connection->get($this->append_token($this->_api_url.$uri));
break;
case 'post':
$response = $this->connection->post($this->append_token($this->_api_url.$uri), $data);
break;
}
}
catch (facebookException $e)
{
$this->_errors[] = $e;
if ( $this->_enable_debug )
{
echo $e;
}
}
return $response;
}
public function errors()
{
return $this->_errors;
}
public function last_error()
{
if ( count($this->_errors) == 0 ) return NULL;
return $this->_errors[count($this->_errors) - 1];
}
public function append_token($url)
{
return $this->session->append_token($url);
}
public function set_callback($url)
{
return $this->session->set_callback($url);
}
public function enable_debug($debug = TRUE)
{
$this->_enable_debug = (bool) $debug;
}
}
class facebookConnection {
// Allow multi-threading.
private $_mch = NULL;
private $_properties = array();
function __construct()
{
$this->_mch = curl_multi_init();
$this->_properties = array(
'code' => CURLINFO_HTTP_CODE,
'time' => CURLINFO_TOTAL_TIME,
'length' => CURLINFO_CONTENT_LENGTH_DOWNLOAD,
'type' => CURLINFO_CONTENT_TYPE
);
}
private function _initConnection($url)
{
$this->_ch = curl_init($url);
curl_setopt($this->_ch, CURLOPT_RETURNTRANSFER, TRUE);
}
public function get($url, $params = array())
{
if ( count($params) > 0 )
{
$url .= '?';
foreach( $params as $k => $v )
{
$url .= "{$k}={$v}&";
}
$url = substr($url, 0, -1);
}
$this->_initConnection($url);
$response = $this->_addCurl($url, $params);
return $response;
}
public function post($url, $params = array())
{
// Todo
$post = '';
foreach ( $params as $k => $v )
{
$post .= "{$k}={$v}&";
}
$post = substr($post, 0, -1);
$this->_initConnection($url, $params);
curl_setopt($this->_ch, CURLOPT_POST, 1);
curl_setopt($this->_ch, CURLOPT_POSTFIELDS, $post);
$response = $this->_addCurl($url, $params);
return $response;
}
private function _addCurl($url, $params = array())
{
$ch = $this->_ch;
$key = (string) $ch;
$this->_requests[$key] = $ch;
$response = curl_multi_add_handle($this->_mch, $ch);
if ( $response === CURLM_OK || $response === CURLM_CALL_MULTI_PERFORM )
{
do {
$mch = curl_multi_exec($this->_mch, $active);
} while ( $mch === CURLM_CALL_MULTI_PERFORM );
return $this->_getResponse($key);
}
else
{
return $response;
}
}
private function _getResponse($key = NULL)
{
if ( $key == NULL ) return FALSE;
if ( isset($this->_responses[$key]) )
{
return $this->_responses[$key];
}
$running = NULL;
do
{
$response = curl_multi_exec($this->_mch, $running_curl);
if ( $running !== NULL && $running_curl != $running )
{
$this->_setResponse($key);
if ( isset($this->_responses[$key]) )
{
$response = new facebookResponse( (object) $this->_responses[$key] );
if ( $response->__resp->code !== 200 )
{
$error = $response->__resp->code.' | Request Failed';
if ( isset($response->__resp->data->error->type) )
{
$error .= ' - '.$response->__resp->data->error->type.' - '.$response->__resp->data->error->message;
}
throw new facebookException($error);
}
return $response;
}
}
$running = $running_curl;
} while ( $running_curl > 0);
}
private function _setResponse($key)
{
while( $done = curl_multi_info_read($this->_mch) )
{
$key = (string) $done['handle'];
$this->_responses[$key]['data'] = curl_multi_getcontent($done['handle']);
foreach ( $this->_properties as $curl_key => $value )
{
$this->_responses[$key][$curl_key] = curl_getinfo($done['handle'], $value);
curl_multi_remove_handle($this->_mch, $done['handle']);
}
}
}
}
class facebookResponse {
private $__construct;
public function __construct($resp)
{
$this->__resp = $resp;
$data = json_decode($this->__resp->data);
if ( $data !== NULL )
{
$this->__resp->data = $data;
}
}
public function __get($name)
{
if ($this->__resp->code < 200 || $this->__resp->code > 299) return FALSE;
$result = array();
if ( is_string($this->__resp->data ) )
{
parse_str($this->__resp->data, $result);
$this->__resp->data = (object) $result;
}
if ( $name === '_result')
{
return $this->__resp->data;
}
return $this->__resp->data->$name;
}
}
class facebookException extends Exception {
function __construct($string)
{
parent::__construct($string);
}
public function __toString() {
return "exception '".__CLASS__ ."' with message '".$this->getMessage()."' in ".$this->getFile().":".$this->getLine()."\nStack trace:\n".$this->getTraceAsString();
}
}
class facebookSession {
private $_api_key;
private $_api_secret;
private $_token_url = 'oauth/access_token';
private $_user_url = 'me';
private $_data = array();
function __construct()
{
$this->_obj =$CI =& get_instance();
$fb_api_id = $CI->db->get_where('settings', array('code' => 'SITE_FB_API_ID'))->row()->string_value;
$fb_api_secret = $CI->db->get_where('settings', array('code' => 'SITE_FB_API_SECRET'))->row()->string_value;
$this->_api_key = $fb_api_id;
$this->_api_secret = $fb_api_secret;
$this->_token_url = $this->_obj->config->item('facebook_api_url').$this->_token_url;
$this->_user_url = $this->_obj->config->item('facebook_api_url').$this->_user_url;
$this->_set('scope', $this->_obj->config->item('facebook_default_scope'));
$this->connection = new facebookConnection();
if ( !$this->logged_in() )
{
// Initializes the callback to this page URL.
$this->set_callback();
}
}
public function logged_in()
{
return ( $this->get() === NULL ) ? FALSE : TRUE;
}
public function logout()
{
$this->_unset('token');
$this->_unset('user');
}
public function login_url($scope = NULL)
{
$url = "http://www.facebook.com/dialog/oauth?client_id=".$this->_api_key.'&redirect_uri='.urlencode($this->_get('callback'));
if ( empty($scope) )
{
$scope = $this->_get('scope');
}
else
{
$this->_set('scope', $scope);
}
if ( !empty($scope) )
{
$url .= '&scope='.$scope;
}
return $url;
}
public function login($scope = NULL)
{
$this->logout();
if ( !$this->_get('callback') ) $this->_set('callback', current_url());
$url = $this->login_url($scope);
return redirect($url);
}
public function get()
{
$token = $this->_find_token();
if ( empty($token) ) return NULL;
// $user = $this->_get('user');
// if ( !empty($user) ) return $user;
try
{
$user = $this->connection->get($this->_user_url.'?'.$this->_token_string());
}
catch ( facebookException $e )
{
$this->logout();
return NULL;
}
// $this->_set('user', $user);
return $user;
}
private function _find_token()
{
$token = $this->_get('token');
if ( !empty($token) )
{
if ( !empty($token->expires) && intval($token->expires) >= time() )
{
// Problem, token is expired!
return $this->logout();
}
$this->_set('token', $token);
return $this->_token_string();
}
if ( !isset($_GET['code']) )
{
return $this->logout();
}
if ( !$this->_get('callback') ) $this->_set('callback', current_url());
$token_url = $this->_token_url.'?client_id='.$this->_api_key."&client_secret=".$this->_api_secret."&code=".$_GET['code'].'&redirect_uri='.urlencode($this->_get('callback'));
try
{
$token = $this->connection->get($token_url);
}
catch ( facebookException $e )
{
$this->logout();
redirect($this->_strip_query());
return NULL;
}
$this->_unset('callback');
if ( $token['access_token'] )
{
if ( !empty($token->expires) )
{
$token->expires = strval(time() + intval($token->expires));
}
$this->_set('token', $token);
redirect($this->_strip_query());
}
return $this->_token_string();
}
private function _get($key)
{
$key = '_facebook_'.$key;
return $this->_obj->session->userdata($key);
}
private function _set($key, $data)
{
$key = '_facebook_'.$key;
$this->_obj->session->set_userdata($key, $data);
}
private function _unset($key)
{
$key = '_facebook_'.$key;
$this->_obj->session->unset_userdata($key);
}
public function set_callback($url = NULL)
{
$this->_set('callback', $this->_strip_query($url));
}
private function _token_string()
{
return 'access_token='.$this->_get('token')->access_token;
}
public function append_token($url)
{
if ( $this->_get('token') ) $url .= '?'.$this->_token_string();
return $url;
}
private function _strip_query($url = NULL)
{
if ( $url === NULL )
{
$url = ( empty($_SERVER['HTTPS']) ) ? 'http' : 'https';
$url .= '://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
}
$parts = explode('?', $url);
return $parts[0];
}
}
I am not sure what is going on with this library. On line 451 you are looking in the $token array for the values that got returned and then it goes through a very convoluted way of setting that in the CI session and then instantly call it back from the CI session.
Line 458 sets the token into the session and then on 462 they return it but by calling a method that calls a method that returns session->userdata('token').
That seems to be why its failing on 490 because it gets the value in the session data but then tries finding the data for ->access_token on top of the returned value and that does not exist.
dump out $token before line 462 and see if it is an object or an array. If it's ann array then that would explain why ->access_token on 490 does not work. If it is an object then I would change line 462 to
return 'access_token='.$token->access_token;
or whatever the dump of $token says the value of the object is (I am assuming it is access_token) and see if that works. if it does then you have to figure out why they wrote all these extra steps and what it will be used for. If not, call it good.
Facebook has a library written that is available on github that you can just drop in the library dir in codeigniter and it will work fine. I would suggest dropping this class you are using and just use the one Facebook provides. This way you can learn how to integrate with Facebook right from their developer site and if they ever change their API calls, you do not have to rewrite code; you just replace the two files in the library dir.
https://github.com/facebook/facebook-php-sdk/tree/master/src
Hope this helps.
I want to make redirection after login action to previous URL. Please tell me how to do that?
Store the page before Login into Session, After login , read the previous page url from the session and redirect the use to that page.
You can pass the "return" URL as a parameter to the login page. i.e http://yourserver.com/login/?return=http%3a%2f%2fyourserver.com%2fsomedir%2fsomething%2f. After a successful login you then use the get parameter to redirect by using a simple HTTP header location:http://yourserver.com/somedir/something/.
This is, for example, practiced in different Google and Microsoft services where there is a single page for signing in and different services that require the user to be loogged in.
You may this use Action helper I wrote some time ago. Cheers!
class Your_Controller_Action_Helper_GoBack
extends Zend_Controller_Action_Helper_Abstract
{
/**
* #todo Check if redirecting to the same domain
* #param bool $required Throw exception?
* #param bool $validateDomain
* #param bool $allowSubdomain
* #param string $alternative URL to redirect to when validation fails and required = true
* #param string $anchorParam Request parameter name which holds anchor name (#). Redirect to page fragment is not allowed according to HTTP protocol specification, but browsers do support it
* #throws Zend_Controller_Action_Exception if no referer is specified and $required == false or $checkdomain is true and domains do not match
*/
public function direct($required = true, $anchorParam = null, $validateDomain = true, $allowSubdomain = false, $alternative = null)
{
$front = Zend_Controller_Front::getInstance();
$request = $front->getRequest();
$referer = $request->getPost('http_referer');
if (empty($referer)) {
$referer = $request->getServer('HTTP_REFERER');
if (empty($referer)) {
$referer = $request->getParam('http_referer');
}
}
if (null === $alternative) {
$alternative = $request->getPost('http_referer');
if (null === $alternative) {
$alternative = $request->getParam('http_referer');
}
}
if ($referer) {
if ($validateDomain) {
if (!$this->validateDomain($referer, $allowSubdomain)) {
$this->_exception($alternative);
}
}
if (null != $anchorParam) {
$referer .= '#' . $request->getParam($anchorParam);
}
$redirector = new Zend_Controller_Action_Helper_Redirector();
$redirector->gotoUrl($referer);
} elseif($required) {
$this->_exception($alternative);
}
}
/**
* #throws Zend_Controller_Action_Exception With specified message
* #param string $message Exception message
* #param string $alternative
*/
private function _exception($alternative = null, $message = 'HTTP_REFERER is required.')
{
if ($alternative) {
if (Zend_Uri::check($alternative)) {
$redirector = new Zend_Controller_Action_Helper_Redirector();
$redirector->gotoUrl($alternative);
}
}
throw new Zend_Controller_Action_Exception($message);
}
/**
* Check if domain from current url and domain from specified url are the same
* #param string $url Target url
* #param string $allowSubdomain false
*/
public function validateDomain($url, $allowSubdomain = false)
{
if (!Zend_Uri::check($url)) {
return false;
}
$currentUri = $this->getCurrentUri();
$uri = Zend_Uri_Http::fromString($currentUri);
$currentDomain = $uri->getHost();
$uri = Zend_Uri_Http::fromString($url);
$target = $uri->getHost();
if ($allowSubdomain) {
// Find second dot from the end
$pos = strrpos($target, '.');
if (false !== $pos) {
$pos = strrpos(substr($target, 0, $pos), '.');
if (false !== $pos) {
$target = substr($target, $pos+1);
}
}
}
if ($target === $currentDomain) {
return true;
}
return false;
}
/**
* #return string Current URL
*/
public function getCurrentUri()
{
$request = $this->getRequest();
$path = $request->getRequestUri();
$server = $request->getServer();
$host = $request->getServer('HTTP_HOST');
$protocol = $request->getServer('SERVER_PROTOCOL');
if (!empty($protocol)) {
$protocol = explode('/', $protocol);
$protocol = strtolower($protocol[0]);
}
if (empty($protocol)) {
$protocol = 'http';
}
$baseUrl = $protocol . '://' . $host . '/';
$path = trim($path, '/\\');
$url = $baseUrl . $path;
return $url;
}
/**
* Like str_replace, but only once
* #param string $search
* #param string $replace
* #param string $subject
*/
public function replaceOnce($search, $replace, $subject)
{
$firstChar = strpos($subject, $search);
if($firstChar !== false) {
$beforeStr = substr($subject, 0, $firstChar);
$afterStr = substr($subject, $firstChar + strlen($search));
return $beforeStr . $replace . $afterStr;
} else {
return $subject;
}
}
}