i am using codeigniter (template) library in codeigniter. I always repeat template library code in every function. will you help me to reduce the code.
public function index(){
//Load View in template file
$this->template->title('Contacts')
->set_layout($this->admin_home_layout)
->set_partial('header', 'admin/admin_share/admin_header')
->set_partial('sidebar', 'admin/admin_share/admin_sidebar')
->set_partial('footer', 'admin/admin_share/admin_footer')
->set_partial('hidenbar', 'admin/admin_share/admin_hidenbar')
->build('admin/admin_home');
}
These 4 lines i am using in every function. how i can use one time in one controller and how to get in function.
->set_partial('header', 'admin/admin_share/admin_header')
->set_partial('sidebar', 'admin/admin_share/admin_sidebar')
->set_partial('footer', 'admin/admin_share/admin_footer')
->set_partial('hidenbar', 'admin/admin_share/admin_hidenbar')
This is how I do it ( applicable for any framework in PHP that has similar way of rendering views):
Suppose that the controllers look like this:
<?php
class AdminController extends BaseController{
public function viewData($id){
// do something
$this->render('something static 1');
$this->render('customview');
$this->render('something static 2');
$this->render('something static 3');
}
}
?>
What I would do is create a base controller to do this rendering tasks ( and more repetitive stuffs):
<?php
class MyBaseController extends BaseController{
protected function renderAll($param){
if(empty($param)){
return false;
}
$this->render('something static 1');
$this->render($param);
$this->render('something static 2');
$this->render('something static 3');
return true;
}
}
?>
Once this is done, I will simply inherit the newly created controller in all my controllers, such as:
<?php
class AdminController extends MyBaseController{
public function viewData($id){
// do something
$this->renderAll('customview');
}
}
?>
You can re-use this in any controller action you want to, just inherit the custom base controller class.
you can set them in the constructor:
public function __construct() {
parent::__construct();
//Do your stuf here
}
Or you could create a function for it:
function set_partials() {
$this->template->set_partial('header', 'admin/admin_share/admin_header')
->set_partial('sidebar', 'admin/admin_share/admin_sidebar')
->set_partial('footer', 'admin/admin_share/admin_footer')
->set_partial('hidenbar', 'admin/admin_share/admin_hidenbar')
}
In this second case, you're index would look like this:
public function index(){
//Load View in template file
$this->template->title('Contacts')
->set_layout($this->admin_home_layout);
$this->set_partials();
$this->template->build('admin/admin_home');
}
i suggest a different logic, just a custom array for your partials like this :
protected $partials = [
'header' => 'admin/admin_share/admin_header',
'sidebar' => 'admin/admin_share/admin_sidebar',
'footer' => 'admin/admin_share/admin_footer',
'hidenbar' => 'admin/admin_share/admin_hidenbar'
];
and use this function to build layout
public function build_layout()
{
$this->template->title('Contacts')->set_layout($this->admin_home_layout);
foreach($this->partials as $k => $partial){
$this->template->set_partial($k,$partial);
}
$this->template->build('admin/admin_home');
}
Related
I am new to Laravel. I have some functions in PaymentController. I want to call those functions from SmartpaySController. Here is the function which is available in PaymentController. Help me to call that function by staying in SmartpaySController.
public function getPaymentFailed($paymentId) {
$transactionData = $this->paymentRepo->find($paymentId);
if($transactionData) {
$data['quote'] = $this->quoteRepo->getQuoteById($transactionData->quote_id);
$data['metaTitle'] = 'Payment failed';
$data['returnMessage'] = $transactionData->return_message;
return view('payment::payment.quote_payment_failed', $data);
}
}
Thank you.
Instead of calling controller methods, the better practice is that you can create traits like: app/Traits and extend in controller
//trait
trait traitName {
public function getData() {
// .....
}
}
//Controller
class ControlelrName extends Controller {
use TraitName;
}
I recomend you to not call functions from one controller to another.
Make Helpers, Resources or implement same feature in other way
Never use controllers as object
But if you want to do it anyway you can use:
SomeController.php
class SomeController extend Controller {
public function someFunction(Request $request) {
// Here Some Code
}
}
YourController.php
use SomeController;
...
public function getPaymentFailed(Request $request, $paymentId) {
$controller_data = (new SomeController)->someFunction($request);
$transactionData = $this->paymentRepo->find($paymentId);
if($transactionData) {
$data['quote'] = $this->quoteRepo->getQuoteById($transactionData->quote_id);
$data['metaTitle'] = 'Payment failed';
$data['returnMessage'] = $transactionData->return_message;
return view('payment::payment.quote_payment_failed', $data);
}
}
Change:
public function getPaymentFailed($paymentId)
to:
public static function getPaymentFailed($paymentId)
This will make it staticly available in your SmartpaySController by doing:
PaymentController::getPaymentFailed($paymentId);
You can make use of Real-Time Facades
Using real-time facades, you may treat any class in your application
as if it were a facade.
To generate a real-time facade, prefix the namespace of the imported
class with Facades:
//...
use use Facades\App\Http\Controllers\SomeController;
//...
return SomeController::getPaymentFailed($request, $paymentId);
Why is it that whenever I redirect something through the constructor of my Codeigniter 4 controller is not working?
<?php namespace App\Controllers\Web\Auth;
class Register extends \App\Controllers\BaseController
{
function __construct()
{
if(session('username')){
return redirect()->to('/dashboard');
}
}
public function index()
{
// return view('welcome_message');
}
}
But if I put it inside index it's working as expected.
public function index()
{
if(session('username')){
return redirect()->to('/dashboard');
}
}
The thing is, I do not want to use it directly inside index because I it need on the other method of the same file.
As per the Codeigniter forum, you can no longer use the redirect method in the constructor to redirect to any of the controllers.
Please refer the below link for more information
https://forum.codeigniter.com/thread-74537.html
It clearly states that redirect() will return a class instance instead of setting a header and you cannot return an instance of another class while instantiating a different class in PHP.
So that's why you can't use redirect method in constructor.
Instead, what I can suggest to you is that use the header method and redirect to your desired controller.
<?php namespace App\Controllers\Web\Auth;
class Register extends \App\Controllers\BaseController
{
function __construct()
{
if(session('username')){
header('Location: /dashboard');
}
}
}
If that's not feasible or difficult to achieve you can follow the below code
<?php namespace App\Controllers\Web\Auth;
class Register extends \App\Controllers\BaseController
{
function __construct()
{
//call to session exists method
$this->is_session_available();
}
private function is_session_available(){
if(session('username')){
return redirect()->to('/dashboard');
}else{
return redirect()->to('/login');
}
}
}
The 2nd solution will be more interactive than the first one. And make sure the method is private. So that it should not be called from other class instances.
The community team has also given a solution to look into the controller filter.
https://codeigniter4.github.io/CodeIgniter4/incoming/filters.html
Please refer to the thread. I hope it may help you in finding a better solution.
In this case you shouldn't even be doing this kind of logic in your controllers. This should be done in a filter and not your controllers.
So you have your controller Register.
You should create a filter in your app/filters folder something like checkLogin.php
That filter should have the following structure:
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class CheckLogin implements FilterInterface
{
/**
* Check loggedIn to redirect page
*/
public function before(RequestInterface $request, $arguments = null)
{
$session = \Config\Services::session();
if (session('username')) {
return redirect()->to('/dashboard');
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Do something here
}
}
Then in your app/config/Filters.php your should add the filter to the desired controller.
public $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
'toolbar' => \CodeIgniter\Filters\DebugToolbar::class,
'honeypot' => \CodeIgniter\Filters\Honeypot::class,
'checkLogin' => \App\Filters\CheckLogin::class,
];
// List filter aliases and any before/after uri patterns
public $filters = [
'checkLogin' => ['before' => ['Register']],
];
For more information on filters and how to use then please check the documentation.
https://codeigniter.com/user_guide/incoming/filters.html?highlight=filters
You can then even create filters to your other controllers that would redirect to this one in case the user is not logged in.
Codeigniter 4 using initController() to create constructor.
You can't use redirect() inside __construct() or initController() function.
But you can use $response parameter or $this->response to call redirect in initController() before call another function in controller;
<?php namespace App\Controllers\Web\Auth;
class Register extends \App\Controllers\BaseController
{
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);
if(session('username')){
$response->redirect(base_url('dashboard')); // or use $this->response->redirect(base_url('dashboard'));
}
}
public function index()
{
// return view('welcome_message');
}
}
I just got into CI 4 and i had the same issue as you did, since i've been approaching the login system as with CI 3.
So here is the proper way of doing it right. Enjoy.
Codeigniter 4 do not has any return on Constructor, but you can use like this
public function __construct()
{
if (!session()->has('user_id')) {
header('location:/home');
exit();
}
}
Don't forget to use exit()
But, you better use Filters
I need interacts with a .tpl file in my adminController class, but when I try to do that, this error appears
Fatal error: Call to undefined method RiddlePageController::getCacheId() in /home/USER/public_html/prestashop/modules/RiddleModule/controllers/admin/RiddlePage.php on line 48
This is my admin controller code:
class RiddlePageController extends AdminController {
public function __construct()
{
$this->html = '';
$this->display = 'view';
$this->meta_title = $this->l('metatitle');
$this->module = "RiddleModule";
parent::__construct();
}
public function initContent()
{
$this->postProcess();
$this->show_toolbar = true;
$this->display = 'view';
$this->meta_title = $this->l('Modulo');
parent::initContent();
}
public function initToolBarTitle()
{
$this->toolbar_title = $this->l('Titulo');
}
public function initToolBar()
{
return true;
}
public function renderView() {
$this->context->smarty->assign(
array(
'img1' => "http://www.free-3dmodels.com/image/Flowers-3D-Model-3662994d.png",
'img2' => "http://www.all3dmodel.com/Images/39.jpg"
)
);
// in return have error "getCacheId"
return $this->display(__FILE__, 'content.tpl', $this->getCacheId());
// return "<b>This works fine!!</b>";
}
my tpl file have only {$img1} and {$img2} for testing.
Maybe I do all wrong, and this is not the best way to make in my own admin page.
Your error is because the AdminController class doesn't have the getCacheId method.
To answer to your question you have to made some little fix.
First (extends ModuleAdminController not AdminController):
class AdminRiddlePageController extends ModuleAdminController
{
}
Then if you want to view your custom tpl, place a view.tpl file in:
prestashop/modules/RiddleModule/views/templates/admin/riddlepage/helpers/view/
or
prestashop/modules/RiddleModule/views/templates/admin/riddle_page/helpers/view/ (I don't remember well if the underscore is necessary)
And your renderView method should be like this:
public function renderView()
{
/* Your code */
/* Use this snippet to assign vars to smarty */
$this->tpl_view_vars = array(
'myvar' => 1,
'secondvar' => true
)
return parent::renderView();
}
AdminController class has not an implementation of display method you use to render TPL.
You can use something like this after set module var:
$this->module->display(_PS_MODULE_DIR_.$this->module->name.DIRECTORY_SEPARATOR.$this->module->name.'.php', 'content.tpl')
Good luck.
As #TheDrot told us, the answer are in using $this->context->smarty->fetch(location), but not in renderList, but in the return statement of renderView is OK and prestashop get the tpl file and load correctly the smarty variables. Ex:
public function renderView(){
$this->context->smarty->assign(
array(
'img1' => "http://www.free-3dmodels.com/image/Flowers-3D-Model-3662994d.png",
'img2' => "http://www.all3dmodel.com/Images/39.jpg"
)
);
return $this->context->smarty->fetch(_PS_MODULE_DIR_ . "RiddleModule/controllers/front/prueba.tpl");
}
The file location isn't important to load the TPL file in this case
I have TheParentController and the inheritating TheChildController, which should assign $moreData to the template, but the render() method should be called in TheParentController.
Is there any function/service for this case? I expect anything like
$this->get('templating')->assignDataForTemplate('moreData', $moreData);
class TheParentController
{
public function myAction($param1) {
return $this->render('template.html.twig', array(
'someData' => $someData
));
}
}
-
class TheChildController
{
public function myAction($param1) {
// !
// Is there any function like "assignDataForTemplate"?
$this->get('templating')->assignDataForTemplate('moreData', $moreData);
// /!
return parent::myAction($param1);
}
}
I would like to avoid something like
// ...
public function myAction($param1, $moreData = null) {
return $this->render('template.html.twig', array(
'someData' => $someData,
'moreData' => $moreData
));
}
}
As far as I'm aware, there is no such way to do this currently. If you go through the sources, you'll see that calling $templating->render() is actually calling TwigEngine->render().That calls Twig_Template->render() which outputs the template to the client.
I fully understand why you might be using HMVC but I believe this approach might be overcomplicating things for you. If you have common code between controllers - just create a static class which can be called directly. Afterwards move your common logic/code there and call it whenever you need it.
Otherwise, you might need to stick with the code you're trying to avoid (or similar workaround) for now.
You could try something like this, so that the parent is unaware of the child.
<?php
class TheParentController {
public function myAction () {
$data = $this->getMyActionData();
return $this->render('template', $data);
}
protected function getMyActionData () {
return [
'someDefault' => 5
];
}
}
class TheChildController extends TheParentController {
// If using annotation based routing override myAction
// with call to parent function and new #Route tag in doc block
protected function getMyActionData () {
$parentData = parent::getMyActionData();
return array_merge($parentData, [
'childData' => 11
]);
}
}
I am using Widget in my Header layout.
In My controller .I have set following variables:
public $testVal="testing";
I have created a widget in YII and I use it in my Header layout:
<?php $this->beginWidget('CountryWithCityWidget'); $this->endWidget();?>
My widget Code is:
<?php
class CountryWithCityWidget extends CWidget
{
public $countryList;
public $cityList;
public function init()
{
print_r($testVal);// I need $testVal testing here from view ***How ????***
echo "==============================";
die;
parent::init();
}
public function run()
{
$this->render('countryWithCityWidget',array('countryList' => $this->countryList,'locationDetailList'=>$this->cityList));
}
}
?>
In view I will get it like $this->testVal and then from view I want to send $testVal to widget where I am using it.
How can I do that?
Try
$this->widget('CountryWithCityWidget', array(
'testVal' => $testVal
));
and add a property testVal to your widget class. Also pass your $testVal var to your view.
for further reading