Hi I am trying to load the Setting and Accessible to all the Controllers and views. Is there a nice way to do this.
As I mentioned, you can modify the controller that all other controllers extend from, and add the variables to the __construct() function. For instance in my 5.3 project, all controllers extend App\Http\Controllers\Controller. In that controller, add (or update, if the function exists) something like this:
protected $settings; // Protected so child controllers can't modify it
public function __construct() {
$this->settings = Settings::first();
}
You can do all sorts of logic here and set up any variables you want. Then in the child controllers, all you have to do to access them is use $this->settings, like
if($this->settings->my_setting == TRUE)
If you want to use it in a view, you'll have to pass it into the view. If you want to share it will all views, you can follow the instructions here.
Related
For sharing data with all views I read in documentation we can create
View::share('key', 'value');
I found that also we can make View Composer to share data with only some specific views.
But how to actually share data with only some specific controllers?
Few controllers we list to have injected some variables, objects arrays etc ready to use.
One Idea that comes to my mind is to create for them middleware... But I don't think it should be done something this way
Looking for this in documentation and web but cannot found, so how actually share data only with some specific controllers that we want to?
Maybe this will help for you:
Some snippets from conetix.com.au/blog/simple-guide-using-traits-laravel-5
You can use use ExampleCode; in the controller you wish
<?php
namespace App\Traits;
trait ExampleCode
{
public function asd()
{
return [1,2,3];
}
}
namespace App\Something;
use App\Traits\ExampleCode;
class Someclass
{
use ExampleCode;
public $yourarray;
public function __construct()
{
$this->yourarray = $this->asd();
}
public function hi(){
dd($this->yourarray);
}
}
If multiple controllers need to have access to the same data, then you may want to consider creating a base controller that they inherit from and setting that data in the constructor of the controller.
Alternatively you can store it in the session and retrieve it from there in the controllers that need it.
Maybe it's better to use decomposition for this purpose. Write some service class for your data, bind it to your service container and then inject it into controllers constructor or action methods.
I have a question about making some elements available in any view file
Lets say im building a webshop and on every page i will be having my sidebar, shoppingcart, user greeting in the top.
How can i make these things available in all my view files?
I could make a class, lets say class Frontend
I could do something like this:
class Frontend {
static $me;
public function get(){
if(!self::$me){
self::$me = new self();
}
return self::$me;
}
private function getShoppingCart(){
// do things
}
public function getData(){
return array(
'Username' => User::find(1)->UserName,
'Cart' => $this->getShoppingCart()
);
}
}
Now in my controller i could pass this Frontend object into the view
View::make('file.view')->with(array('data' => Frontend::get()->getData()));
But this way i will end up with a god class containing way too much stuff and in every controller method i would have to pass these data, which is not relevant to the controller method
Is there a way in Laravel that makes specific data available across all view files?
Thanks!
Use share:
View::share('name', 'Steve');
as per http://laravel.com/docs/responses#views
To keep everything clean, every part of the page should be its own *.blade.php file which would be put together using a master template of sorts.
master.blade.php
#yield('includes.sidebar')
#yield('users.greeting')
#yield('store.shoppingcart')
Then you can use view composers so that each time these views are loaded, the data you want is injected into them. I would probably either create a new file which would get autoloaded, or if you have service providers for the separate portions of your app that these views would use, it would also go great in there.
View::composer('users.greeting', function($view)
{
$view->with('user', Auth::user());
});
In this case, it would make the user model available inside your view. This makes it very easy to manage which data gets injected into your views.
You are close with your 'god class' idea.
Setting a $data variable in a basecontroller has helped me with similar issues
class BaseController extends Controller {
protected $data;
public function __construct() {
$this->data['Username'] = User::find(1)->UserName
$this->data['Cart'] = $this->getShoppingCart()
}
}
class Frontend extends BaseController {
function someMethod(){
View::make('file.view', $this->data)
}
}
I simply do not mean how to define a global variable/constant in CodeIgniter.
Let me explain:
I have made a theme engine which is select-able from the current logged in user's control panel. This engine is not very complicated, but a simple folder. anyway, what I do across the application, is that I write one line of code to get the current theme selected by the user. I use a one line of code to get the name, and then store it in a variable:
$theme_name = $this->theme->get_theme_with_slash(false);
And then, I user $theme_name like this to get the proper view:
$this->load->view($theme_name.'result', $data);
And in all of my controllers that loads view I should repeat this process. What I need, is to call the function which gets the theme_name and store in the variable and then use the variable/session/function across the application. My approach currently is the helper's function which is a little less convenient compared to session/variable.
I got this from the manual and this what I have at the top of my config/config.php file: (i have a custom config set to paypal testing)
// HOW TO USE - For example if there's $config['foo'] = 'bar';
// in the config
// using $this- >config->item('foo') will be 'bar'.
// example for my paypal testing:
$config['paypaltest']=0;
http://ellislab.com/codeigniter%20/user-guide/libraries/config.html
and how to access in a controller:
$paypaltest = $this->config->item('paypaltest');
Create A core controller, since your process requires logical operations then you need a method for that.
application/core/MY_Controller.php
class MY_Controller Extends CI_Controller
{
protected $default_theme = 'theme';
public function __construct()
{
parent::__construct();
}
public function get_theme()
{
//your code for selecting the current theme selected from
//the database
$theme_from_db = '';
return $theme_from_db == NULL ? $this->default_theme : $theme_from_db;
}
}
Your Controller must extend MY_Controller
application/controller/view.php
class view extends MY_Controller
{
public function index()
{
$this->load->view($this->get_theme().'result', $data);
}
}
in code igniter global constants can be defined in
config->constants.php
even you no need to load it,it automatically autoloaded by CI automatically.
In Codeigniter all constant is defined inside application/config/constant.php.
like: define("CONSTANTNAME","value");
Constant degined here is accessible throughout all pages, ie; controllers, models and views
I am working on building a lightweight MVC, mainly for the learning process but I would like it to be good enough to use eventually.
Below is a basic example/demo of how a basic controller might would look, let's assume the URI has been processed and routed to this controller and these 2 methods.
1) I need to get data from database/cache/etc... inside my Model classes, I just need help on how I should load my models into my example controller below, you can see that I have added this below $profileData = $this->model->getProfile($userId) that is just made up and does not exist's, how could I get something like that to work though? Or should I load the model into the class a different way?
2) A lot of pages will require a user to be logged into the site. SHould I process that part below in the controller to check if a user is logged in, example, before building the profile page, check if user is logged in, if not then build a login page instead and add these checks inside of each controller method/page?
/**
* Example Controller
*/
class User_Controller extends Core_Controller {
// domain.com/user/id-53463463
function profile($userId)
{
//GET data from a Model
$profileData = $this->model->getProfile($userId);
$this->view->load('userProfile', $profileData);
}
// domain.com/user/friends/
function friends()
{
//GET data from a Model
$friendsData = $this->model->getFriendlist();
$this->view->load('userFriends', $friendsData);
}
}
core
abstract class Core_Controller {
protected $view;
protected $model;
function __construct(DependencyContainer $dependencyContainer){
$this->view = new Core_View();
//$this->view = $dependencyContainer->get(view);
}
}
There are probably tons of ways to accomplish what you are trying.
The "easiest" is probably to just override the constructor and instantiate the model directly.
in User_Controller:
public function __construct(DependencyContainer $dc) {
parent::__construct($dc);
$this->model = new User_Model();
}
I'm guessing that you are looking for something a little more automated though. If you want the Model to have the same name as the controller minus "_Controller", just use get_class($this) in the constructor and use PHP's string functions to parse out what you want. Once you have that in a variable, you can use that variable to instantiate the model:
in Core_Controller:
public function __construct(DependencyContainer $dc) {
$this->view = new Core_View();
// $model_class should be 'User_Model' now
$model_class = str_replace('_Controller', '_Model', get_class($this));
// now instantiate the model
$this->model = new $model_class();
}
I haven't actually worked with any framework that can only have one model associated with each controller (except may CakePHP? I can't remember). With Symfony, the models and controllers are completely decoupled so you can use any model with any controller. You just instantiate the model as need. Symfony use the Doctrine ORM so for example, in a controller action, if you needed a model you would do something like this:
$model = Doctrine::getTable('User');
It might be worthwhile to consider a design more like that in order to promote a decoupled design and I promise that you will want more than one model in some controller at some point.
2.) As far as authentication. Something that seems to be fairly common is to have some sort of setting (whether in a config file or a member variable) that says whether or not the current action needs the user to be authenticated. This is processed each time the action runs (Yii calls these kinds of things filters). If the user needs to be logged in, it stores the page that they are trying to access, and then redirects them to a log in page (you should only ever have to create one). Once they properly authenticate, it will redirect them back to where they were originally heading.
I have a list of constants (I'm using them as an enum), some are define statements, and some are just global variables.
Where am I suppose to put them in the MVC framework so I can use them for both my model and my controller that needs to reference it?
I'd rather not stick it into config/constants.php since they shouldn't be called except for by this model and the controllers that use it.
Edit 1: Clarification
To be more specific, I have my message_model model and it has a bunch of constants that I need that are stored in message_model_constants.php. Where should I put message_model_constants.php and is there a way to have it automatically included by the controller that loads message_model when message_model is not (and I don't want it to be) auto-loaded.
Edit 2:
I really don't want to have the constants auto-loaded except for when I use the model
Go to application/config/constants.php and define your constant their and you can use your constants on Model-View-Controller of CI not include "Helper" and "Library"
But in your case I prefer you to create a php file that has your constants and rename it to something like my_constants_helper.php.
In your model or controller __construct just
$this->load->helper('my_constants');
And hooray you can access them =)
You can choose to load a particular config file when you load a particular model in the controller. For instance in your file:
application/controllers/messages.php
You would use a line like this:
$this->config->load('messages');
If you include it at the top of your controller like this
function __construct() {
$this->config->load('messages');
$this->load->model('message_model');
}
Then all of those constants will be available to all the functions and methods in the given controller. You then call each config constant like:
$this->config->item('item name')
And you can name protected $variables; in the construct as well for shorter syntax.
If you are using these config constants and the message model in multiple different controllers you may want make a "Library" file that then loads both the config and the model and declares all variables there.
extending Brennan Novak answer, you can simplify your code by loading your config file in the model constructor. That way, you only have to load the model in your controllers and everything else is done automatically.
Model
class Message_model extends Model {
function __construct()
{
parent::Model();
$this->load->config('message_model_constants');
}
...
}
Controller
class Some_controller extends Controller {
function __construct()
{
parent::Controller();
$this->load->model('message_model');
}
...
}
As already stated, your config files should be application/config/message_model_constants.php
For global configs, add to the config/config.php or create a config/application.php and then load the config, then the item.
$this->config->load('application'); // or autoload this - $autoload['config'] = array('application');
$this->config->item('item name');
Have you considered just adding your constants to your Message_Model Class? You'll then reference them by self::ConstantName inside the Class and Message_Model::ConstantName outside the class. This would also prevent name space collision.