Why I cannot declare or init session globally in the BaseController.php ?
BaseController.php
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*/
abstract class BaseController extends Controller
{
/**
* Instance of the main Request object.
*
* #var CLIRequest|IncomingRequest
*/
protected $request;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = ['BotMenu_helper',
'Channel_helper',
'Day_helper',
'Dir_helper',
'File_helper',
'Key_helper',
'Login_helper',
'Notification_helper',
'Response_helper',
'Security_helper',
'Ticker_helper',
'Utility_helper',
'RSS_helper',
'User_helper'];
/**
* Constructor.
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
// Preload any models, libraries, etc, here.
// E.g.: $this->session = \Config\Services::session();
$this->session = \Config\Services::session();
$this->language = \Config\Services::language();
$this->language->setLocale($this->session->lang);
}
}
When I do post :
$routes->post('ProcessCheckoutApp', 'App\Controllers\Front\AppPayment::ProcessCheckoutApp', ['as' => 'ProcessCheckoutApp']);
I got this error :
message": "CodeIgniter\\Session\\Session and Psr\\Log\\LoggerAwareTrait define the same property ($logger) in the composition of CodeIgniter\\Session\\Session. However, the definition differs and is considered incompatible. Class was composed",
I didn't declare session in any file.
Finally found the problem.
Do not init globally session in the BaseController. Because if you have run a thirdparty autoload.php it will causing the error.
Example that make session error :
public $session;
function __construct()
{
require_once APPPATH . 'ThirdParty/vendor/autoload.php';
$this->session = session();
}
The correct way is init the session above the autoload.php
public $session;
function __construct()
{
$this->session = session();
require_once APPPATH . 'ThirdParty/vendor/autoload.php';
}
Related
I cannot find the problem using
$routes->resource
Please help me figure out what is the problem.
This is how I put my routes resource in config routes :
$routes->resource('ApiManageBanner', ['controller' =>'App\Controllers\ApiData\ApiManageBanner']); // get, put, create, delete
Recently I just move all my project to the newest codeigniter 4 version 4.2.6 from the previous version 4.1.2
This is my controllers :
<?php
namespace App\Controllers\ApiData;
use App\Controllers\BaseController;
use CodeIgniter\RESTful\ResourceController;
use Codeigniter\API\ResponseTrait;
class ApiManageBanner extends ResourceController
{
use ResponseTrait;
function __construct()
{
}
// equal to get
public function index() {
echo "Test";
}
// equal to post
public function create() {
}
// equal to get
public function show($id = null) {
}
// equal to put
public function update($id = null) {
}
// equal to delete
public function delete($id = null) {
}
}
I just try a simple to echo "Test".
But I got this error :
I search everywhere but cannot find the problem related to the error.
If I change the routes name to 'ApiManageBanners' using 's' :
$routes->resource('ApiManageBanners', ['controller' =>'App\Controllers\ApiData\ApiManageBanner']); // get, put, create, delete
It is working.
But I cannot change my routes name because my application is reading
'ApiManageBanner' not 'ApiManageBanners'
I am very curious what cause the problem. It is not working for almost all my resources api controller routes.
I found the problem. According to the error it is related to session. When I check all my file. I found that I always init the :
$this->Session = \Config\Services::session();
In all my controller and model __construct();
function __construct()
{
$this->Session = \Config\Services::session();
}
So I remove it and init globaly in BaseController.php
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\CLIRequest;
use CodeIgniter\HTTP\IncomingRequest;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*/
abstract class BaseController extends Controller
{
/**
* Instance of the main Request object.
*
* #var CLIRequest|IncomingRequest
*/
protected $request;
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = [''];
/**
* Constructor.
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
// Preload any models, libraries, etc, here.
// E.g.: $this->session = \Config\Services::session();
$this->session = \Config\Services::session();
$this->language = \Config\Services::language();
$this->language->setLocale($this->session->lang);
}
}
Then the error is gone.
How can I load a model in ...\app\Config\Autoload.php?
Code:
namespace Config;
use CodeIgniter\Config\AutoloadConfig;
class Autoload extends AutoloadConfig {
public function __construct() {
//load here
//i've tried,
$my_model = new \App\Models\My_model();
$my_model = model("App\Models\My_model");
}
Nothing is working.
What is the correct way?
Looking for help.
Thanks in advance.
This really depends on where you want to use this model. Autoloading does not work the same way as codeigniter 3 where everything would be put into the same super object.
If what you want is to use this model in a bunch of controllers then you can add that to your baseController in your initController function. Let's say you want to autoload the article model:
public $article;
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
$this->article = new \App\Models\ArticleModel();
}
Now all your controllers that extend to your baseController can access this model with $this->article.
If what you want is to use the autoload and you can do that too, but not in a construct, for that you should use the classMap property.
/**
* -------------------------------------------------------------------
* Class Map
* -------------------------------------------------------------------
* The class map provides a map of class names and their exact
* location on the drive. Classes loaded in this manner will have
* slightly faster performance because they will not have to be
* searched for within one or more directories as they would if they
* were being autoloaded through a namespace.
*
* Prototype:
*
* $classmap = [
* 'MyClass' => '/path/to/class/file.php'
* ];
*
* #var array
*/
public $classmap = [
'Article' => APPPATH . 'Models/ArticleModel.php'
];
But this option is more for classes that exist outside the normal codeigniter structure. So I would advise into using the first option.
I am new to PHP OOP and CodeIgniter and I need help. I am using CodeIgniter 4 and trying to preload model logas_model in BaseController.php:
<?php
namespace App\Controllers;
/**
* Class BaseController
*
* BaseController provides a convenient place for loading components
* and performing functions that are needed by all your controllers.
* Extend this class in any new controllers:
* class Home extends BaseController
*
* For security be sure to declare any new methods as protected or private.
*
* #package CodeIgniter
*/
use App\Models\Admin\logas_model;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;
class BaseController extends Controller
{
/**
* An array of helpers to be loaded automatically upon
* class instantiation. These helpers will be available
* to all other controllers that extend BaseController.
*
* #var array
*/
protected $helpers = ['form', 'session', 'html', 'number'];
protected $logas;
/**
* Constructor.
*/
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
// Do Not Edit This Line
parent::initController($request, $response, $logger);
//--------------------------------------------------------------------
// Preload any models, libraries, etc, here.
//--------------------------------------------------------------------
///$this->session = \Config\Services::session();
$this->logas = new logas_model();
}
}
Model logas_model code:
<?php namespace App\Models\Admin;
use CodeIgniter\Model;
use Config\Services;
class logas_model extends Model
{
protected $table = 'veiksmai_logs';
protected $primaryKey = 'id';
protected $returnType = 'array';
protected $useSoftDeletes = true;
protected $useTimestamps = TRUE;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
protected $allowedFields = ['uid', 'veiksmas'];
public function get_all_veiksmai()
{
return $this->select("CONCAT(`user`.`vardas`, ' ', `user`.`pavarde`) AS `user_vardas_pavarde`, `veiksmai_logs`.`veiksmas`, `veiksmai_logs`.`created_at`, `veiksmai_logs`.`id`")
->join('user', 'user.id = veiksmai_logs.uid')
->orderBy("`veiksmai_logs`.`created_at`", 'DESC')
->findAll();
}
public function add_veiksmas($veiksmas)
{
$session = Services::session()->get();
$data = [
'uid' => $session['uid'],
'veiksmas' => $veiksmas
];
return $this->insert($data);
}
}
And then, in other controller, which extends Controller, I am trying to use that preloaded model by using it's function like this:
$this->logas->add_veiksmas('Created User.');
Full that Controller code:
<?php namespace App\Controllers\Admin;
use App\Models\Admin\vartotojai_model;
use CodeIgniter\Controller;
class Vartotojai extends Controller
{
private $vartotojai;
public function __construct()
{
$this->vartotojai = new vartotojai_model();
}
public function index()
{
$this->logas->add_veiksmas('Created User.');
$this->data['vartotojai'] = $this->vartotojai->get_all_vartotojai();
echo view('templates/Admin/Header', ['title' => 'Vartotojai']);
echo view('Admin/Vartotojai/Index', $this->data);
echo view('templates/Admin/Footer');
}
}
But it is not working.
What am I doing wrong?
Change Controller
class Vartotojai extends Controller
{
into BaseController
class Vartotojai extends BaseController
That may be because you have not extended BaseController to Vartotojai controller.
class Vartotojai extends BaseController
Please try this.
Kindly note: whenever you are preloading(Models, helpers, libraries e.t.c), you need to extend the BaseController on all the controllers that will be using that model.In your case you preloaded the model correctly but you did not extend your controller to the BaseController. Use the below format in your controllers:
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
class ClassName extends BaseController
{
//your functions and code
}
?>
In my views i am extending a default blade template which acts as my Master Template. I have a ViewComposer setup which serves this template with a number of variables.
I have come to a situation where i need to access one of these variables within my index.blade.php which is the page initiating the #extends function.
Do the variable passed via the ViewComposer reach the scope of the initial view? Or will i need to create another ViewComposer to pass the same variable.
ViewComposer
<?php
namespace App\Http\ViewComposers;
use Illuminate\View\View;
use Illuminate\Http\Request;
use App\Repositories\UserRepository;
use Sentinel;
use App\ProjectUsers;
class MasterComposer
{
/**
* The user repository implementation.
*
* #var UserRepository
*/
protected $users;
private $request;
/**
* Create a new profile composer.
*
* #param UserRepository $users
* #return void
*/
public function __construct(Request $request)
{
$this->request = $request;
// Dependencies automatically resolved by service container...
$uid = Sentinel::getUser()->id;
$this->users = ProjectUsers::where("user_id", '=', $uid)->get();
}
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view)
{
$view->with('projects', $this->users);
$view->with('activeProject', $this->request->session()->get("activeProject"));
}
}
ComposerServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ComposerServiceProvider extends ServiceProvider {
/**
* Register bindings in the container.
*
* #return void
*/
public function boot() {
// Using class based composers...
view ()->composer ( 'admin/layouts/default', 'App\Http\ViewComposers\MasterComposer' );
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
//
}
}
index.blade.php
#extends('admin/layouts/default')
{{ $activeProject }}
This ultimately give me an undefined variable error.
Undefined variable: activeProject (View: /home/laravel/public_html/base/resources/views/admin/index.blade.php)
Yes, all variables which are available in the master layout will be passed to any of its children.
Since you're using #extends in your content layout you can use this
#extends('admin/layouts/default', ['activeProject' => $activeProject])
If this doesn't work you might need to pass it through your controller
I Want to extend Symfony2 Controller to my project that is using API but I am having error of a non object use getParameter() function look at my code:
namespace Moda\CategoryBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class ApiController extends Controller
{
/**
* #var String
*/
protected $_host;
/**
* #var String
*/
protected $_user;
/**
* #var String
*/
protected $_password;
public function __construct()
{
$this->_host = $this->container->getParameter('api_host');
$this->_user = $this->container->getParameter('api_user');
$this->_password = $this->container->getParameter('api_password');
}
}
And next Controller
namespace Moda\CategoryBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
class CategoryController extends ApiController
{
/**
* #Route("/category", name="_category")
* #Template()
*/
public function indexAction()
{
return array('name' => 'test');
}
}
And the end, I got this Fatal Error:
FatalErrorException: Error: Call to a member function getParameter()
on a non-object in (..)
I try to use $this->setContainer() but it doesn't work. Do you have any idea how can I slove this problem?
If your controller is not defined as service, The constructor execution of the controller is not persisted.
You have two options to solve your situation:
Define the controller as a service and inject the parameters you need using dependency injection.
Add an init method in the controller, or on a parent abstract controller, and call the init method, before the action you need to have these parameters available;
You cant use container in Controller __construct at reason that when constructor called where is none container set yeat.
You can simply define some simple methods in controller like
class ApiController extends Controller
{
protected function getApiHost()
{
return $this->container->getParameter('api_host');
}
}
I wonder if something crazy like this would work? Instead of overriding the constructor, override the setContainer method? I haven't tried it...just thinking out loud.
namespace Moda\CategoryBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ApiController extends Controller
{
/**
* #var String
*/
protected $_host;
/**
* #var String
*/
protected $_user;
/**
* #var String
*/
protected $_password;
public function setContainer(ContainerInterface $container = null)
{
parent::setContainer($container);
$this->_host = $this->container->getParameter('api_host');
$this->_user = $this->container->getParameter('api_user');
$this->_password = $this->container->getParameter('api_password');
}
}