I want to create a global array inside a controller class in laravel. I searched and explored many resources but couldn't find a proper answer. I want that array to be accessible by all the methods in that controller. Currently I have tried this :
public $members=array(1,2); Global variable
`global $members;` //Inside function
echo $members[0]; //Inside function
I tried to access the data in the array in the function but got a null exception.Please help me out.
You should use the $this keyword.
class x extends Controller {
public $members = array(1,2);
public function myAction(){
echo $this->members[0];
}
}
Related
Okay there are questions about the same topic before but they don't help to fully understand this topic
SO SuggestionFirst
SO Suggestion Second
All the code is just to illustrate the situation, So this is the structure
A helper function which does something
namespace App\Helpers;
class Pets{
public function limit($string,$limit,$start = 0){
return substr($string,$start,$limit);
}
}
Now in order to use this helper, since it's a class so i need to create an object like this
CODE SAMPLE FIRST
namespace App\Objects;
use App\Helpers\Pets;
class User{
public function getShortUserName(){
$name = auth()->user()->first_name.' '.auth()->user()->last_name;
$pet = new Pets;
return $pet->limit($name,10);
}
}
But somewhere I got to know that if you add Facades before your namespace, you can call the function statically even if they are non static function like this
CODE SAMPLE SECOND
namespace App\Objects;
use Facades\App\Helpers\Pets;
class User{
public function getShortUserName(){
$name = auth()->user()->first_name.' '.auth()->user()->last_name;
return Pets::limit($name,10);
}
}
Now what I want to know is I have 2 sample codes with namespace as follows
use App\Helpers\Pets;
use Facades\App\Helpers\Pets;
By adding the Facades I can call the function statically but how, that's not a valida namespace in my app
What laravel doing behind the scene, I am so confused
Thank you for your time ;)
What you are describing is Laravels Real-Time Facades.
You can find documentation of the functionality here:
https://laravel.com/docs/6.x/facades#real-time-facades
I will not enter too much in details but this is a simple explanation of what's behind the scenes when you use facades in laravel.
Let's suppose you define a custom class with some public methods:
namespace Test;
class Foo
{
public function test()
{
return 'test';
}
}
Then you have to define a facade for this class:
namespace Test1;
class BarFacade
{
// In laravel this is called in the Facade abstract class but it is actually implemented
// by all the facades you add across the application
public static function getFacadeAccessor()
{
// In laravel you can also return a string which means that the object
// will be retrieved from the container.
return new \Test\Foo();
}
// In laravel this method is defined in the Facade abstract class
public static function __callStatic($method, $args)
{
$object = self::getFacadeAccessor();
return call_user_func_array([$object, $method], $args);
}
}
Then, you have to define the alias in the $aliases array of the config.app file. These aliases are parsed by laravel and registered using the php built-in function class_alias (see Illuminate/Foundation/AliasLoader.php)
class_alias('Test\Foo', 'BarFacade', true);
// You can also create an alias for the facade itself
class_alias('Test1\BarFacade', 'FooBar', true);
Then you can simply call the facades:\
var_dump(BarFacade::test());
var_dump(\Test1\BarFacade::test());
var_dump(\FooBar::test());
The results would obviously be:
string(4) "test"
string(4) "test"
string(4) "test"
I am creating my model object using new keyword. But each time the two objects created. My code is
class DashBoardController extends Controller
{
public static $count=0;
public function __construct()
{
DashBoardController::$count++;
}
public function dashboard(Request $request)
{
$obj = new DashBoardController();
echo DashBoardController::$count;
}
}
It gives me output as
O/P: 2
The result is right, there are two instances of DashboardController: The one created by the routing and then the one created by the dashboard method.
It seems that it's better yo use $this instead of creating a new instance of a controller.
Inside the dashboard method you are inside an already existing controller!
So here's the code
use App\Video;
class HomeController extends Controller
{
protected $video;
public function index()
{
// $video_to_watch is fetched from db and I want to save it and use it in
// another function in this controller
$this -> video = $video_to_watch;
return view('home', compact('video_to_watch'));
}
public function feedback(Request $request)
{
dd($this -> video);
}
}
feedback returns null for some reason.
when I put the
dd($this -> video);
in index() it works fine, not null.
I have tried what's suggested here: Laravel doesn't remember class variables
but it didn't help.
I'm sure it's something stupid I'm overlooking. But can't seem to figure out what, any help much appreciated.
You can't keep your $video value between 2 different requests. You have to fetch your video data in each request.
use App\Video;
class HomeController extends Controller
{
public function index() {
$myVideo = $this->getMyVideo();
return view('home', $myVideo);
}
public function feedback(Request $request) {
dd($this->getMyVideo);
}
private function getMyVideo() {
// fetch $video_to_watch from db
return $video_to_watch ;
}
}
First of all don't fetch data inside a Controller. It's only 'a glue' between model and view. Repeat. No fetching inside a controller.
Use domain services and dependency injection to get business data and if you want to share this data create shared service (single instance).
-
Putting a data object into a controller property class makes a temporary dependency between method calls. Avoid it. Use services instead.
this supposed to be an MVC framework
(i am learning by doing)
class load{
public function model(){
// some code...
[...] = model[$modelName] = new $modelName();
}
}
this class handles all load option in to the controller..
class _framework{
public $load; // object
public $model; // array
function __construct(){
//some code...
$this->load = new load();
}
}
this is the framework of the controllers
the controller extends this class.
edit:
it should use like this:
class newController extends _framework{
public function index(){
$this->load->model('modelName'); // for loading the model.
$this->model['modelName']->modelMethod(); // for use the model method.
}
}
my problem is where the [...].
how can I get the new model to the array in the framework class??
If you want to get an array out of your model object,
you can define its public method toArray:
class modelName {
public function toArray () {
$array = ...; // get your array here
return $array;
}
}
Then you can call it from outside and get your array:
$myArray = $myModel->toArray();
Your model should encapsulate its data and make them accessible via API like that.
I would not call an array a model though. A model is a layer with many classes serving the purpose of the model - storing your data, peforming their validation, whatever other data-related business logic and providing API to access the data.
Also it is common to capitalize your classes.
I am using the following code to initialize a model from within my controller:
$this->load->model('model_name');
Is it possible to modify the above line somehow so that the model constructor recieves a parameter? I want to use the following code in the model constructor:
function __construct($param_var) {
parent::Model();
$this->$param_var = $param_var; //I'm not even sure this works in PHP..but different issue
}
This would be very helpful so that I can reuse my model classes. Thanks.
UPDATE:
(from one of the answers, my original question is solved..thanks!)
Just to explain why I wanted to do this: the idea is to be able to reuse a model class. So basically to give a simple example I would like to be able to pass an "order_by" variable to the model class so that I can reuse the logic in the model class (and dynamically change the order-by value in the sql) without having to create a separate class or a separate function.
Is this poor design? If so could you please explain why you wouldn't do something like this and how you would do it instead?
You can't pass parameters through the load function. You'll have to do something like:
$this->load->model('model_name');
$this->model_name->my_constructor('stuff');
In the model:
function my_constructor($param_var) {
...
}
Response to update:
You could just pass the order_by value when you're calling your model function. I'm assuming in your controller action, you have something like $this->model_name->get($my_id); Just add your order_by parameter to this function. IMO this makes your model logic more flexible/reusable because the way you were doing it, I assume setting order_by in the constructor will set the order_by value for every function.
In model
<?php
/* Load Model core model */
/* BASEPATH = D:\xampp\htdocs\ci_name_project\system\ */
include BASEPATH . 'core\\Model.php';
class User_model extends CI_Model {
/* Properties */
private $name;
/* Constructor parameter overload */
public function __construct($name) {
$this->set_name($name);
}
/* Set */
public function set_name($name) {
$this->name = $name;
}
/* Get */
public function get_name() {
return $this->name;
}
}
in controller
<?php
class User_controller extends CI_Controller {
public function index() {
/* Load User_model model */
/* APPPATH = D:\xampp\htdocs\ci_name_project\application\ */
include APPPATH . 'models\\User_model.php';
$name = 'love';
/* Create $object_user object of User_model class */
$object_user = new User_model($name);
echo $object_user->get_name(); // love
}
}
I see your reasoning for this, but may I suggest looking at Object-Relational Mapping for your database needs. There is a user-made ORM library for CodeIgniter called DataMapper that I've been using lately. You can use tables in your controllers as objects, and it may be a better fit for your problem.
Instead of using DataMapper i suggested to use IgnitedRecord because that the DataMapper is no longer maintained more over it has been replaced into Ruby
I am using CI ver 3.X, so what I am about to say is it will work for Codeigniter 3.X (and I haven't checked ver 4+ yet).
When I went thru the source code of the function model() in file system/libraries/Loader.php, noticed that it does not support loading the model with construct parameters. So if you want to make this happen you have to change the source code (bold, I know, and I just did).
Down below is how I did it.
1. Firstly, replace line 355
$CI->$name = new $model();
with some modifications:
$_args_count = func_num_args();
if(3 < $_args_count){
$refl = new ReflectionClass($model);
$CI->$name = $refl->newInstanceArgs(array_slice($_args_count, 3));
}else{
$CI->$name = new $model(); // origin source code
}
2. Load the model with a bit difference:
$this->load->model("model_name", "model_name", false, $param_var); // where amazing happens
Now you can have $this->model_name as you wished.