Codeigniter 4 - get instance in helper function - php

how can i get in ci4 instance into helper function? $CI =&get_instance(); <- that was in version 3, how does this go in version Codeigniter 4?

I made a gist for it. here is a way to do it.
Create a helper file, you can name it whatever you want.
Add the following codes to the helper you just created.
Content of the helper file: i.e: utility_helper.php
<?php
$CI_INSTANCE = []; # It keeps a ref to global CI instance
function register_ci_instance(\App\Controllers\BaseController &$_ci)
{
global $CI_INSTANCE;
$CI_INSTANCE[0] = &$_ci;
}
function &get_instance(): \App\Controllers\BaseController
{
global $CI_INSTANCE;
return $CI_INSTANCE[0];
}
Call register_ci_instance($this) at the very beginning of your base controller
Now you may use get_instance() where ever you want just like CI3: $ci = &get_instance()
There are three notes I want to mention
I tested on PHP8 only.
I'm not sure if & is needed when calling get_instance. however, you have the option to use any form you want. so calling $ci = get_instance() is ok too, but you may do $ci = &get_instance() as you wish.
Make sure you change \App\Controllers\BaseController to something appropiate(i.e: your base controller). type hinting is great since IDEs understand them.

Create a common helper to keep the controller instance. Suppose here it is common_helper.php
$CI4 = new \App\Controllers\BaseController;
function register_CI4(&$_ci)
{
global $CI4;
$CI4 = $_ci;
}
In your BaseController
public $user_id;
protected $helpers = ['form', 'url', 'common']; // Loading Helper
public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
register_CI4($this); // Registering controller instance for helpers;
$this->user_id = 4;
}
Now you will get the controller instance in all other helpers. Suppose a new heper user_helper as
function show_user_id()
{
global $CI4;
echo $CI4->user_id; // Showing 4
}
I tested it in PHP Version: 8.0.6

For me, this is the best solution for me:
if (!function_exists('getSegment'))
{
/**
* Returns segment value for given segment number or false.
*
* #param int $number The segment number for which we want to return the value of
*
* #return string|false
*/
function getSegment(int $number)
{
$request = \Config\Services::request();
if ($request->uri->getTotalSegments() >= $number && $request->uri->getSegment($number))
{
return $request->uri->getSegment($number);
}
else
{
return false;
}
}
}
source: https://forum.codeigniter.com/thread-74755.html

I get it (using CodeIgniter4):
in controller:
helper('login');
$isLog=isLogged($this,"user","passwd");
if($isLog)
....
else
....
in helper:
use App\Models\Loginmodel as Loginmodel;
function isLogged($ci,$e,$c){
$ci->login = new Loginmodel;
$ci->login->Like('paassword',$c);
$id=$ci->login->select('id')->where('username',$e)->findAll();
return $id;
}
I hope this helps.

Related

How to reach doctrine repository in private (non-route) function in symfony5?

When I need to access an entity repository in a public function I usually inject it with the args for that function, such as
public function showAction(DebitPeriod $debitPeriod, ExtraOpeningRepository $extraOpeningRepository)
However, when I have a private function (which is only serving as a sub-function to one of the controller routes) how can I reach the entity repository from there?
I want to be able to use it like this
use App\Repositories\ExtraOpeningRepository;
private function assembleEntries($units,$day = null) {
$eor = new ExtraOpeningRepository;
}
or like this
private function assembleEntries($units,$day = null, ExtraOpeningRepository $extraOpeningRepository) {
The error I get is this:
Too few arguments to function
App\Repository\ExtraOpeningRepository::__construct(), 0 passed
I don't want to have to chain it onward all the way from the route controller like this:
public function showAction(DebitPeriod $debitPeriod, ExtraOpeningRepository $extraOpeningRepository) {
$units = 1;
$dataset = $this->assembleEntries($units,null,$extraOpeningRepository);
}
private function assembleEntries($units,$day = null, ExtraOpeningRepository $extraOpeningRepository) {
//do stuff
}
IS there a way to achieve it cleaner, without the mess of the above example?
As per Cerad's comment, this is the successful result =)
use App\Repository\ExtraOpeningRepository;
class EntryController extends AbstractController
{
private $extraOpeningRepository;
public function __construct(ExtraOpeningRepository $extraOpeningRepository)
{
$this->extraOpeningRepository = $extraOpeningRepository;
}
private function assembleEntries($units,$day = null)
{
$extraOpenings = $this->extraOpeningRepository->findForDay($output[$i]['dateToFetch']);

Is it possible to invoke an instance of a class whose name is passed as a variable?

I'm developing in Laravel 9, though I assume this is Php-specific. Example below of what I'm trying to achieve: Imagine I have a controller named HomeController.php with a getData() method that returns something I need...
<?php
namespace App\Http\Controllers;
class HomeController
{
public function getData()
{
return [my data]
}
}
And I want to be able to call that class and method in a dynamic way, and assign my data to $data...
<?php
use App\Http\Controllers\HomeController;
class Example
{
public $className = 'HomeController';
public $method = 'getData';
public function index()
{
$instance = new $this->className;
$method = $this->method;
$data = $instance->$method();
}
}
I have a variation of this setup in my application, and it's not working. I get the following error: Class "HomeController" not found.
If I replace $this->className with HomeController it works. Keep in mind $className will be passed from elsewhere, I want to avoid hard-coding class names into my Example class.
It is true that I will still need to include them all at the top anyway, but I just want to know if it's possible to pass a class name like that. Unless there's a way to dynamically include those too, but I doubt it.
Edit: Tim's answer in the comments worked great. Here is a fixed version:
<?php
use App\Http\Controllers\HomeController;
class Example
{
public $className = 'App\\Http\\Controllers\\HomeController'; // Change 1
public $method = 'getData';
public function index()
{
$instance = app()->make($this->className); // Change 2
$method = $this->method;
$data = $instance->$method();
}
}

Php Calling the functions of same class one after another

I want to write something like (laravel uses):
View::make('FooBarView')->with('foo', $foo)
->with('bar', $bar);
My knowledge and imagination made me to use new self instances. But I don't think that this is the best idea around and I could not handle it.
Google couldn't help me because of my bad keywords I think. I don't want to make you write code for me for sure but what is the name of this design pattern or whatever?
In laravel's source, with function uses
return $this;
But how to use it after make?
By the way, in this example; with method helps you to set variables for view's render.
To call what the function returns, the function will have to return something that is possible to call.
In this case, you could for example return "this":
class View {
/**
* #returns View
*/
public static function make($foo) {
/* do stuff, return new View instance */
return new View();
}
/**
* #returns View
*/
public function with($foo, $bar){
/* do stuff */
return $this;
}
}
That way, whenever you call with you will get the class instance back, which in turn will be callable:
View::make("foo")->with("foo")->with("bar");
// Will be same as:
$v = View::make("foo");
$v = $v->with("foo");
$v = $v->with("bar");

Get returned of controller action in my own abstact library (Zend Framework)

Hello I am trying to retrieve the values ​​returned by a controller action in my own library abstract in one of the methods of dispatch of Zend Framework, I wonder if this feat possible and if so how do it.
My code is as follows:
IndexController
class IndexController extends My_Controller
{
public function init()
{
/* Initialize action controller here */
}
public function indexAction()
{
// action body
return 'hello world';
}
}
My_Controller
abstract class My_Controller extends Zend_Controller_Action
{
/**
* Initialize Core_Controller
* #param Zend_Controller_Request_Abstract $request
* #param Zend_Controller_Response_Abstract $response
* #param array $invokeArgs
*/
public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array())
{
parent::__construct($request, $response, $invokeArgs);
$this->_helper->viewRenderer->setNoRender();
}
public function preDispatch()
{
//something here
}
public function postDispatch()
{
//something here
}
public function dispatch()
{
//something here
}
}
I need to get the value of what was returned in the controllador in this library in order to transform it into json and then print to screen.
Thnk
In ZF 1 there isn't a way to get the return value from the controller action. This value is never used or captured by Zend Framework itself.
Take a look at Zend/Controller/Action.php line 516 (ZF 1.11.11) and this is the point where ZF calls your controller action, and the return value is not captured or used.
public function dispatch($action)
{
// Notify helpers of action preDispatch state
$this->_helper->notifyPreDispatch();
$this->preDispatch();
if ($this->getRequest()->isDispatched()) {
if (null === $this->_classMethods) {
$this->_classMethods = get_class_methods($this);
}
// If pre-dispatch hooks introduced a redirect then stop dispatch
// #see ZF-7496
if (!($this->getResponse()->isRedirect())) {
// preDispatch() didn't change the action, so we can continue
if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) {
if ($this->getInvokeArg('useCaseSensitiveActions')) {
trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"');
}
$this->$action(); // <--- line 516 - this calls your action
} else {
$this->__call($action, array());
}
}
$this->postDispatch();
}
// whats actually important here is that this action controller is
// shutting down, regardless of dispatching; notify the helpers of this
// state
$this->_helper->notifyPostDispatch();
}
As you can see, the value returned by the controller is never used. Also, in ZF2, they are changing the way controller actions work so the return values actually have meaning so you may want to think of a different approach.
The quickest thing I can think of at the moment would be instead of trying to return a value from the controller, just set a registry value that you can fetch later.
e.g.
public function returnAction()
{
// ...
Zend_Registry::set('controller_return_value', 'hello world');
}
and then later, in your plugin or wherever you are trying to get the value:
try {
$retval = Zend_Registry::get('controller_return_value');
} catch (Zend_Exception $ex) {
$retval = null; // no return value set by controller
}

Dynamic method call in OOP

I don't have alot of experience with OOP programming in PHP, and my search has given no result but solutions to direct methods. What I need is this:
// URL Decides which controller method to load
$page = $_GET['page'];
// I want to load the correct controller method here
$this->$page();
// A method
public function home(){}
// Another method
public function about(){}
// e.g. ?page=home would call the home() method
EDIT: I've tried several of the suggestions, but what I get is a memory overload error message. Here is my full code:
<?php
class Controller {
// Defines variables
public $load;
public $model;
public function __construct() {
// Instantiates necessary classes
$this->load = new Load();
$this->model = new Model();
if (isset($_GET['page'])) {
$page = $_GET['page'];
$fc = new FrontController; // This is what crashes apparently, tried with and without ();
}
}
}
If I understand your question correctly, you'd probably want something more like this:
class FrontController {
public function home(){ /* ... */ }
public function about(){ /* ... */ }
}
$page = $_GET['page'];
$fc = new FrontController;
if( method_exists( $fc, $page ) ) {
$fc->$page();
} else {
/* method doesn't exist, handle your error */
}
Is this what you're looking for? The page will look at the incoming $_GET['page'] variable, and check to see whether your FrontController class has a method named $_GET['page']. If so, it will be called; otherwise, you'll need to do something else about the error.
You can call dynamic properties and methods using something like this:
$this->{$page}();
Use a class.
Class URLMethods {
public function home(){ ... }
public function about(){ ... }
}
$requestedPage = $_GET['page'];
$foo = new URLMethods();
$foo->$requestedPage();
You can achieve this by using call_user_func. See also How do I dynamically invoke a class method in PHP?
I think you'd like also to append another string to the callable functions like this:
public function homeAction(){}
in order to prevent a hacker to call methods that you probably don't want to be.

Categories