I would like to have a variable $user_profile available in most of my view files, without me having to create the variable in each controller file. At the moment I have things working but I was wondering if there is a better solution
I have some code to populate a variable
$user_profile = YumUser::model()->findByPk(Yii::app()->user->id)->profile;
Then a parent class
class Controller extends CController {
public function getUserProfile()
{
$user_profile = YumUser::model()->findByPk(Yii::app()->user->id)->profile;
}
}
Then I have all other controllers inheriting the Controller class, for example
class DashboardController extends Controller
{
public function actionIndex()
{
$user_profile = parent::getUserProfile();
$this->render('index', array('user_profile' => $user_profile));
}
}
Then finally in the view file I can simply access the $user_profile variable.
Create class field in your base controller class:
class Controller extends CController {
public $user_profile;
public function init()
{
parent::init();
$this->user_profile = YumUser::model()->findByPk(Yii::app()->user->id)->profile;
}
}
Don't need to pass it directly to view:
public function actionIndex()
{
$this->render('index');
}
Then you can access it in view using $this:
// index.php
var_dump($this->user_profile);
You already have a getter defined, so you can use $this->userProfile from both, your controllers and your views. I'd only add a caching logic to avoid multiple queries to the database:
class Controller extends CController
{
protected $_userProfile=false;
/*
* #return mixed a User object or null if user not found or guest user
*/
public function getUserProfile()
{
if($this->_userProfile===false) {
$user = YumUser::model()->findByPk(Yii::app()->user->id);
$this->_userProfile = $user===null ? null : $user->profile;
}
return $this->_userProfile;
}
For user profile info, I populate a small number of variables upon login using setState to store the data.
In your UserIdentity class after a successful authentication, you can store data similar to this:
$userRecord = User::model()->find("user_name='".$this->username."'");
$this->setState('display_name',
(isset($userRecord->first_name)) ?
$userRecord->first_name : $userRecord->user_name);
Then in any view, it can be accessed like:
echo (isset(Yii::app()->user->display_name) ?
Yii::app()->user->display_name : 'Guest');
Related
I will give below code example to better explain:
class BaseController extends Controller
{
public $globalCurrencies;
public $currentCurrency;
public $globalLanguages;
public $currentLanguage;
public function __construct()
{
$this->globalCurrencies = $this->getCurrencies();
$this->globalLanguages = $this->getLanguages();
$this->middleware(function ($request, $next) {
$this->currentCurrency = $this->getCurrentCurrency();
$this->currentLanguage = $this->getCurrentLanguage();
return $next($request);
});
}
CartController
class CartController extends BaseController
{
public function __construct()
{
parent::__construct();
}
BaseController sets up base variables for the app. The cart is using some of them like (current currency). Some of the variables are session based so in base construct there is middleware used to get session data in the constructor). For this part, everything works and cart has access to baseController properties.
Problem occurs here:
class OrderController extends BaseController
{
public function loadPaymentsAndDelivery(Request $request)
{
$cart = new Cart;
dd($cart->globalCurrencies) // WORKS
dd($cart->currentCurrency) // NULL
}
}
Basically, on a new Cart instance, I can access every property created without middleware. Without middleware, I cannot access the session to set up the cart. Method loadPaymentsAndDelivery is loaded via ajax but I tried directly call the method and the properties were still null.
Can somebody explain why this is happening?
Problem
Session::get not working in Base Controller
Below case does not shows correct session value
Login Controller
class LoginController extends \App\Http\Controllers\Web\BaseController
{
public function Login() {
return View("UserManagement.Auth.Login.login");
}
}
Base Controller
class BaseController extends Controller
{
public function __construct() {
if(\Session::get("CurrentLanguage") != null) {
dd('here');
\App::setLocale(\Session::get("CurrentLanguage"));
}
else {
dd('here1');
\Session::put("CurrentLanguage", "en");
\App::setLocale("en");
}
}
}
Below case shows correct session value
Base Controller
class BaseController extends Controller
{
}
Login Controller
class LoginController extends \App\Http\Controllers\Web\BaseController
{
public function Login() {
if(\Session::get("CurrentLanguage") != null) {
dd('here');
\App::setLocale(\Session::get("CurrentLanguage"));
}
else {
dd('here1');
\Session::put("CurrentLanguage", "en");
\App::setLocale("en");
}
return View("UserManagement.Auth.Login.login");
}
}
Here the problem is, I have to use Base Controller in many controllers. Is there any way to make the session work in Base Controller?
According to the following URL, you are no longer able to use the session in the constructor of a controller in Laravel 5.3. This is because at the point in time that your controller is constructed the middleware that deals with the session has not yet run. Apparently, it was never an intended feature to be able to access the session in the controller. Since this affected sessions, you will not be able to access the authenticated user in the controller's constructor either.
A way around this however is to use a closure based middleware in your constructor.
class BaseController extends Controller
{
public function __construct()
{
$this->middleware(function ($request, $next) {
if(\Session::get("CurrentLanguage") != null) {
dd('here');
\App::setLocale(\Session::get("CurrentLanguage"));
}
else {
dd('here1');
\Session::put("CurrentLanguage", "en");
\App::setLocale("en");
}
return $next($request);
});
}
}
This works because your controller is simply defining a middleware to run at a later time after which the session is available.
The reason it works in your second example is that you're accessing the session in a controller method. At that point in time the session is available because the middleware will have run.
I have my application within Zend Framework 1. I'm using Zend_Auth to manage sessions. Below is how I check authentication within the IndexController class:
class IndexController extends Zend_Controller_Action
{
public function init()
{
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$this->view->user = $auth->getIdentity();
}
}
public function indexAction()
{
}
}
Basically it just sets a view variable of user to whatever is in the auth object. Within my view I can check if the user variable is set and act appropriately (e.g. Display "Welcome Tom!" and a logout link)
However, this functionality is not available yet in my other controllers. Rather than duplicate the same code within each init() method, how can I do this? I'm not so sure where to put the code for this.
UPDATE:
I tried to do something like this in the bootstrap file:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initView() {
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$this->view->user = $auth->getIdentity();
}
}
}
..but I get the following error: Notice: Indirect modification of overloaded property Bootstrap::$view has no effect in /var/www/budgetz/application/Bootstrap.php on line 9 Warning: Creating default object from empty value in /var/www/budgetz/application/Bootstrap.php on line 9.
You can use an abstract class inheriting from Zend_Controller_Action like this:
abstract Class Yourlibrary_Controller_ControllerAbstract extends Zend_Controller_Action
{
public function preDispatch()
{
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$this->view->user = $auth->getIdentity();
}
}
}
And yours Controllers inherit Yourlibrary_Controller_ControllerAbstract not Zend_Controller_Action
I have two classes on my Codeigniter project: Users and Profiles
Users:
class Users extends CI_Controller
{
...
Profiles:
class Profiles extends CI_Controller
{
protected function create_user_profile()
{
....
}
...
When a user is created by user controller, a profile should be created immediately. So a function in Users has to call create_user_profile function. Now my question is:
If I make create_user_profile public, one can call it by URL. But if I keep it protected, then how to call it from User controller?
Is there a better way than moving create_user_profile from Profiles controller to Users controller?
Try making a Profiles Library instead :
Libraries/profiles.php
class Profiles
{
protected $CI;
public function __construct()
{
$this->CI =& get_instance(); // Existing Code Igniter Instance
}
public function create_user_profile()
{
// Your Code Here
// can communicate back with CI by using $this->CI
// $this->CI->load->view(....);
// $this->CI->load->model(...);
// ETC
}
}
controllers/users.php
class Users extends CI_Controller
{
public function my_function(){
$this->load->library('profiles');
$this->profiles->create_user_profile();
}
}
Put it in a different, non-web-controller class. Then you can re-use it from everywhere.
I am trying to build an abstract base controller that will extend all other controllers. So far I have something like:
abstract class BaseController {
protected $view;
protected $user;
public function __construct() {
$this->view = new View; //So a view is accessible to subclasses via $this->view->set();
$this->user = new User; //So I can check $this->user->hasPermission('is_admin');
}
abstract function index();
}
class UserController extends BaseController {
public function index() {}
public function login() {
if($this->user->isLoggedin()) {
redirect to my account
}
else {
$this->view->set('page_title', "User Login");
$this->view->set('sidebar', $sidebar); //contains sidebar HTML
$this->view->set('content', $content); //build main page HTML
$this->view->render();
}
}
}
The problem i get is I get errors like this:
Call to a member function set() on a non-object in C:\xampp\htdocs\program\core\controllers\admin.controller.php on line 44
If I put the $user and $views properties in the main controller (ie UserController), everything works fine. But I only want to set up these objects once (in the base controller) and not have to add $this->view = new View; in all my controllers.
FIXED: I overrode my constructors and I thought you couldn't call parent::__construct() on abstract classes.
What you are trying to do should work. Make sure you aren't covering up your constructor in UserController. (i.e., if it has a constructor, it needs to call its parent constructor.)
Otherwise, do some debugging to see where $this->view is being reset.
Your code works for me. You are either overriding your __construct() method in UserController, or you are overridding the view field with something other than a View object.
What you have in this form would work.