Add code to function from another controller - php

In CodeIgniter framework i have two controller files:
controllerA.php and controllerB.php
I need controllerB.php to add code in controllerA.php function
I have no idea how to do it, i checked Codeigniter manual, google and stackoverflow but was not able to find solution
controllerA.php has function:
function get_permission_conditions()
{
return do_action('staff_permissions_conditions', [
'contracts' => [
'view' => true,
'view_own' => true,
'edit' => true,
'create' => true,
'delete' => true,
]);
}
I want controllerB.php to communicate with controllerA.php and add custom code example:
function get_permission_conditions()
{
//Code from controllerA.php
return do_action('staff_permissions_conditions', [
'contracts' => [
'view' => true,
'view_own' => true,
'edit' => true,
'create' => true,
'delete' => true,
//custom code from controllerB.php goes here
]);
}

You should extend controllerA like this:
class controllerA extends CI_Controller{
// All the function will go here
return do_action('staff_permissions_conditions', [
'contracts' => [
'view' => true,
'view_own' => true,
'edit' => true,
'create' => true,
'delete' => true,
]);
}
class controllerB extends controllerA{
public $permission_array;
function __construct() {
$this->permission_array = $this->do_action(); // Here $permission_array will have the array returned by controllerA's function 'do_action'
}
//custom code from controllerB.php goes here
// You can use $permission all over
}

Create a parent controller for both of the and let them both extend that parent and move that method to that parent and let the parent extend CI_Controller .. pretty much like what you did with MY_Controller ...
That's your C_Controller (Parent controller):
class C_Controller extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
// your methods that will be extended
...
}
That's your A_Controller:
class A_Controller extends C_Controller
{
public function __construct()
{
parent::__construct();
}
}
That's your B_Controller:
class B_Controller extends C_Controller
{
public function __construct()
{
parent::__construct();
}
}

Related

Backpack for laravel -> I can't get + Add Inline Create

I want to use the Inline Create functionality of Backpack for Laravel but the button "Add +" doesn't shows up.
I have a 1 to n relationship
The primary model is Inscription and the secondary is InscriptionProduct
This is my code:
Models\Inscription
...
class Inscription extends Model
{
public function product() {
return $this->hasMany('App\Models\InscriptionProduct');
}
...
Models\InscriptionProduct
...
class InscriptionProduct extends Model
{
public function inscription()
{
return $this->belongsTo(Inscription::class);
}
...
Http\Controllers\Admin\InscriptionProductCrudController
...
class InscriptionProductCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
...
Http\Controllers\Admin\InscriptionCrudController
...
class InscriptionCrudController extends CrudController
{
protected function setupCreateOperation()
{
...
$this->crud->addField([
'type' => "relationship",
'name' => 'product',
'ajax' => true,
'inline_create' => true,
// 'data_source' => backpack_url('/admin/inscription-product/inline/create'),
// 'data_source' => backpack_url('inscription/fetch/inscription-product'),
// 'inline_create' => [ 'entity' => 'inscriptionproduct' ]
// These 3 commented lines are alternatives also tried with no results
]);
...
The Relationship is well constructed because I can see the Products I have created via the CRUD of InscriptionProduct
What am I missing?
I solve it to, in your main CrudController, you should call the InLineCreate just below CreateOperation.
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation { store as traitStore; }
Also in my secondary CrudController I had to create a fetch function, something I did
protected function fetchFeatures()
{
return $this->fetch([
'model' => \App\Models\Features::class, // required
'searchable_attributes' => ['name', 'slug'],
'query' => function($model) {
return $model;
} // to filter the results that are returned
]);
return $this->traitFetch();
}

Route is redirecting before calling the controller method

I am using Laravel 5.5.40 along with the Zizaco\Entrust Pacakge
In my routes/web.php file i have the following route setup.
Route::group(['prefix' => 'order'], function() {
Route::get('', 'OrderController#getMe');
});
It is supposed to call the getMe() method inside the OrderController.php but it instead redirects to www.mydomain.co.uk/home
namespace App\Http\Controllers;
class OrderController extends Controller
{
public function getMe() {
return "You got me!";
}
}
As a test, I added a __construct function to the OrderController.php to see if the class was even been loaded.
public function __construct() {
dd("Testing");
}
When accessing www.mydomain.co.uk/order i now get
"Testing"
I can't seem to work out why it is not running the getMe() method. Could anyone possibly shine some light on this please?
I have also tried changing the route to use ClientController#list which works fine.
Contents of ClientController.php
namespace App\Http\Controllers;
use App\Client;
class ClientController extends Controller
{
public function __construct() {
//
}
// Display all the clients
public function list() {
$tabContent = [
'display_type' => 'list',
'data' => Client::orderBy('name', 'asc')->get(),
'view_params' => [
'columns' => [
'name' => 'Client Name',
'address_line_1' => 'Address Line 1',
'town' => 'Town',
'county' => 'County',
'post_code' => 'Post Code'
],
'links' => 'client',
'controls' => True
]
];
return view('tables.list', ['data' => $tabContent]);
}
}
It has become apparent that if the controller does not have the constructor function in it, it will automatically redirect to the root of the URI with no error.
public function __construct() {
//
}

Form custom elements with factories

We are used to work with ZF2, but for our last project, we decided to start with ZF3.
Now I am facing a problem in the form creation.
What I want to do is to create a custom select populated with values retrieved from database.
What I did in ZF2 was creating a class extending a select, with the ServiceLocatorAwareInterface, like:
class ManufacturerSelect extends Select implements ServiceLocatorAwareInterface {
public function init() {
$manufacturerTable = $this->getServiceLocator()->get('Car\Model\ManufacturerTable');
$valueOptions = [];
foreach ($manufacturerTable->fetchAll() as $manufacturer) {
$valueOptions[$manufacturer->getManufacturerId()] = $manufacturer->getName();
}
$this->setValueOptions($valueOptions);
}
public function getServiceLocator() {
return $this->serviceLocator;
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator) {
$this->serviceLocator = $serviceLocator;
}
}
Then, to use it in a form, it was enough to give the full name
$this->add(
array(
'name' => 'manufacturer_id',
'type' => 'Car\Form\Element\ManufacturerSelect'
)
);
Now this is not possible anymore, since the service locator was removed and the use of factories is necessary, but I'm struggling to find how to do the same thing.
Keeping in mind to use factories, I tried this configuration in module.config.php:
'form_elements' => [
'factories' => [
'Car\Form\Element\ManufacturerSelect' => function ($services) {
$manufacturerTable = $services->get('Car\Model\ManufacturerTable');
return new ManufacturerSelect($manufacturerTable);
},
'Car\Form\CarForm' => function ($services) {
$manufacturerTable = $services->get('Car\Model\ManufacturerTable');
return new CarForm($manufacturerTable, 'car-form');
}
]
]
Result: factory of CarForm is always called, but factory of ManufacturerSelect is not.
A simple solution would be to populate the select directly in the form class, but I would prefer to use the factory for the element and reuse it everywhere I want, like I was doing in ZF2.
Does anyone already encountered this problem and found a solution?
Do you add that element in "__construct" function? If so try "init"
EDIT:
First of all you don't need to create a custom select to fill in it via database. Just create a form with factory, fetch data from db in factory and pass to form. And use the data in form class as select's value options.
$this-add([
'type' => Element\Select:.class,
'name' => 'select-element'
'options' => [
'label' => 'The Select',
'empty_option' => 'Please choose one',
'value_options' => $this-dataFromDB
]
]);
If you create form as:
new MyForm();
Form Element Manager doesn't trigger custom elements' factories. But;
$container->get('FormElementManager')->get(MyForm::class);
triggers custom elements' factories. Here's a working example. It's working on ZF3.
Config:
return [
'controllers' => [
'factories' => [
MyController::class => MyControllerFactory::class
]
],
'form_elements' => [
'factories' => [
CustomElement::class => CustomElementFactory::class,
MyForm::class => MyFormFactory::class,
]
]
];
don't forget to add 'Zend\Form' to application config's 'modules'.
Element:
class CustomElement extends Text
{
}
Element Factory:
class CustomElementFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
echo 'element factory triggered';
return new CustomElement();
}
}
Fieldset/Form:
class MyForm extends Form
{
public function init()
{
$this
->add([
'type' => CustomElement::class,
'name' => 'name',
'options' => [
'label' => 'label',
],
])
;
}
}
Fieldset/Form Factory:
class MyFormFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
echo 'form factory triggered';
return new MyForm();
}
}
Controller's Factory:
class MyControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
echo 'controller factory triggered';
return new MyController(
$container->get('FormElementManager')->get(MyForm::class);
);
}
}

ZF 2 - Fatal Error: Call to a member function getPosts() on null

I am creating a website using Zend Framework 2, and I'm using as an example the exercise from the official course of Zend Technology, Zend Framework 2: Fundamentals.
I have a table called posts and I want to show the table content in my home page, ordered by id. These are the codes I have written:
Controller/PostsTableTrait.php
trait PostsTableTrait
{
private $postsTable;
public function setPostsTable($postsTable)
{
$this->postsTable = $postsTable;
}
}
Controller/IndexController.php
class IndexController extends AbstractActionController
{
use PostsTableTrait;
public function indexAction()
{
return new ViewModel(array(
'post' => $this->postsTable->getPosts()
));
}
}
Factory/IndexControllerFactory.php
class IndexControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$serviceManager = $serviceLocator->getServiceLocator()->get('ServiceManager');
$indexController = new IndexController();
$indexController->setPostsTable($serviceManager->get('Rxe\Factory\PostsTable'));
return $indexController;
}
}
Factory/PostsTableFactory.php
class PostsTableFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new PostsTable(PostsTable::$tableName, $serviceLocator->get('Zend\Db\Adapter\AdapterService'));
}
}
Model/PostsTable.php
class PostsTable extends TableGateway
{
public static $tableName = "posts";
public function getPosts()
{
$select = new Select(self::$tableName);
$select->columns(array(
'date',
'title',
'text',
'category'
));
$select->order('id DESC');
return $select;
}
}
config/module.config.php
'controllers' => array(
'invokables' => array(
'Rxe\Controller\Index' => 'Rxe\Controller\IndexController',
'Rxe\Controller\Panel' => 'Rxe\Controller\PanelController'
),
'factories' => array(
'Rxe\Factory\PanelController' => 'Rxe\Factory\PanelControllerFactory'
)
),
'service_manager' => array(
'factories' => array(
'Rxe\Factory\PanelForm' => 'Rxe\Factory\PanelFormFactory',
'Rxe\Factory\PanelFilter' => 'Rxe\Factory\PanelFilterFactory',
'Rxe\Factory\PostsTable' => 'Rxe\Factory\PostsTableFactory',
'Zend\Db\Adapter\AdapterService' => 'Zend\Db\Adapter\AdapterServiceFactory'
)
),
I don't know if the error could be in the getPosts() method. I have tried many different ways to return the query but none of them made any difference, not even showed another error.
You have registered the controller as an 'invokable'. When the the controller manager creates IndexController it will do so without using the IndexControllerFactory; therefore the Rxe\Factory\PostsTable dependency is never set.
To fix this, update module.config.php and register the index controller with your factory class.
'controllers' => [
'factories' => [
'Rxe\Controller\Index' => 'Rxe\Factory\IndexControllerFactory',
],
],
Also (not an error as such) but the IndexControllerFactory calls ->get('ServiceManager') using the service manager.
You could update it to be like this.
class IndexControllerFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $controllerManager)
{
// #var \Zend\ServiceManager\ServiceManager
$serviceManager = $controllerManager->getServiceLocator();
$indexController = new IndexController();
$indexController->setPostsTable($serviceManager->get('Rxe\Factory\PostsTable'));
return $indexController;
}
}

Yii2 Restfull APi RBAC Guest login

I have a rest full API in Yii2. I have the user model, controller and created a new rest action called login.
How can I set the action login to be executed by the guest users?
class UserController extends \yii\rest\ActiveController{
public function actions() {
$actions = parent::actions();
$actions['login'] = [
'class' => 'app\modules\user\actions\user\LoginUserAction',
'modelClass' => $this->modelClass,
'checkAccess' => [$this, 'checkAccess'],
];
return $actions;
}
public function checkAccess($action, $model = null, $params = array()) {
return true;
}
}
You can set the access control rules on the behaviors function of your controller, instead of on the checkAccess property on the action:
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['access'] = [
'class' => AccessControl::className(),
'except' => ['login'],
'rules' => [
[
'allow' => true,
'actions' => ['foo', 'foo2'],
'roles' => ['admin'],
]
],
];
return $behaviors;
}
In this example, the access control is applied to all actions except 'login'. I left the rules part so you can have an example of how you make customized rules.

Categories