Needing help understanding codeigniter 3 behavior
I'm not understanding the controller behavior very well and I ask for help
class Simulado extends CI_Controller {
function __construct(){
parent::__construct();
$this->load->helper('url');
$this->load->helper('funcoes_helper');
$this->load->helper('file');
$this->load->library('session');
$this->load->library('controle_acesso');
$this->load->model('resumoapp_model', 'resumo');
$this->load->model('homeapp_model', 'homeapp');
$this->load->model('simulado_model', 'simulado');
//permissão para acessar app
$this->controle_acesso->acesso();
$this->output->enable_profiler(TRUE);
}
public function index() {
$dados = '0'//todas as materias;
$bdinsert = $this->simulado->set_bd($dados);
$this->load->view('prova',$dados)
}
public function materia () {
$dados = 1; //idamateria
$bdinsert = $this->simulado->set_bd($dados);
$this->load->view('prova',$dados)
}
}
model
public function set_bd ($dados) {
$data = [
'id_mat' = $dados
];
$this->db->insert('simulados', $data);
}
routes.php
$route['default_controller'] = 'home';
$route['404_override'] = 'my404';
$route['translate_uri_dashes'] = FALSE;
$route['app'] = "/app/home";
$route['site'] = "/home";
when accessed through the link http://localhost/escola/app/simulado, the system behaves in the desired way, it writes the value zero once in the database, for example.
accessing the url we have the method of the class, simulated, http://localhost/escola/app/simulado/materia/1/exatas-matematica calls the method in the correct way, but when writing to the database it writes the code of the matter.
I did a test and put the same code of the article method in the index and called the url, and it worked perfectly, writing only once the code of the article in the database.
I need to know why it is recording 3 times in the database when accessing the url is a method of the class and has parameters.
Related
I am trying to implement a widgets library using load->view. I know I can use include to call directly the file and avoid the vars cache issues but just wondering why it does not work.
Here is how I have structured my code:
My Controller:
class Page extends MY_Controller {
public $data = array();
public function __construct() {
parent::__construct();
...
$this->load->library('widgetmanager');
}
public function index($slug = '') {
echo $this->widgetmanager->show(2);
echo $this->widgetmanager->show(1);
}
}
My Library
class WidgetManager
{
private $CI;
public function __construct()
{
$this->CI = & get_instance();
}
public function show($widget_id) {
$data = array();
$widget_id = (int)$widget_id;
$this->CI->db->select('*');
$this->CI->db->from('widget');
$this->CI->db->where('id', $widget_id);
$query = $this->CI->db->get();
$item = $query->row_array();
$data['widget_title'] = $item['title'];
$data['widget_content'] = $item['content'];
$widget = $this->CI->load->view('widget/'.$item['source'], $data, TRUE);
$data['widget_title'] = '';
$data['widget_content'] = '';
$this->CI->load->view('widget/'.$item['source'], $data);
return $widget;
}
}
widget 1: Calls widget/content
widget 2: Calls widget/banner
What is happening is, the vars set on the first widget call (they are same name as second widget call), get cached, meaning values from the first call are passed to same call. It is weird because are different views.
I have tried:
Using clear_vars(): $this->CI->load->clear_vars(), before and after doing load->view on the library.
Calling load->view with empty array, null, etc
Tried to add a prefix with the widget slug to the vars (that works, but I have to send in some way the prefix to the view, so it is not possible due cache issue)
Any ideas?
Here is what should work.
(I took the liberty of simplifying your database call making it require much less processing.)
public function show($widget_id)
{
$data = array();
$widget_id = (int) $widget_id;
$item = $this->CI->db
->get_where('widget', array('id' => $widget_id))
->row_array();
$data['widget_title'] = $item['title'];
$data['widget_content'] = $item['content'];
$widget = $this->CI->load->view('widget/'.$item['source'], $data, TRUE);
//clear the cached variables so the next call to 'show()' is clean
$this->CI->load->clear_vars();
return $widget;
}
On further consideration The call $this->CI->load->clear_vars(); is probably pointless because each time WidgetManager::show() is called the $data var is recreated with exactly the same keys. When the $data var is passed to load->view the new values of $data['widget_title'] and $data['widget_content'] will replace the values in the cached vars using those keys.
My master layout here's below and working fine. I just want little bit more passing a default variable with this master layout that I can get in every pages.
class MY_Controller extends CI_Controller {
public $layout;
function __construct() {
parent::__construct();
$this->layout='layout/master';
}
}
I need to pass variable like below:
function __construct() {
parent::__construct();
$data['msg'] = $this->session->flashdata('usermsg');
$this->layout=('layout/master',$data);
}
How do I get this.
If you are loading up the data dynamically from the controller with the help of $this->layout you can send the data like this.
Method 1:
If you are using the general method to load the data to the view you can use this method.
$this->load->view('profile_view', $data);
This will load the profile_view page along with the $data as you passs into it with the help of array()
Method 2:
If you have created a master Layout and you are passing the data from the controller to the Master Layout you need to do like this.
<?php
public function master_layout () {
$this->template['header'] = $this->load->view('include/header', $this->Front_End_data, true);
$this->template['navigation'] = $this->load->view('include/navigation', $this->Front_End_data, true);
$this->template['center'] = $this->load->view($this->middle, $this->Front_End_data, true);
$this->template['footer'] = $this->load->view('include/footer', $this->Front_End_data, true);
$this->load->view('include/index', $this->template);
?>
In this code the below line alone will be loaded dynamically based on the page which you call in the master Layout.
$this->template['center'] = $this->load->view($this->middle, $this->Front_End_data, true);
In order to pass the data to this center layout you can use the funciton like this.
$data['msg'] = 'Success';
$this->template['center'] = $this->load->view ($this->middle = 'pages/view_oage',$data, true);
$this->master_layout();
And in the page you can get the data to be printed using the foreach loop as follows.
foreach($msg as $value)
{
echo $value;
}
I have a problem. I want to access to a variable from another function. let me explain.
Controller
public function obtener_oplataforma_usuarios() {
$this->load->helper('form');
$this->load->model('usuarios_model');
$plataforma = $this->input->post('id_plataforma');
$data['records'] = $this>usuarios_model>obtener_plataformas_usuarios($plataforma);
$this->load->view('vista_plataforma_usuarios', $data);
}
function grupos($grupo){
$this->load->helper('form');
$this->load->model('usuarios_model');
$plataforma = 'BaD';
$data['records'] = $this->usuarios_model->obtener_grupos($plataforma, $grupo);
$this->load->view('vista_plataforma_usuarios', $data);
}
Model
function obtener_grupos($plataforma, $grupo){
$this->db->select('*');
$this->db->from('usuarios');
$this->db->where('Plataforma', $plataforma);
$this->db->where('grupos', $grupo);
$query = $this->db->get();
return $query->result();
}
I want to access to the variable platforma in the function obtener_oplataforma_usuarios from the function obtener_grupos I tried different things and I still have problems.
Can you help me to solve this issue. and I want to do that because I want to make a query with two validations one is group and the other platforma. My problem is the second one. I recibe the information of plataforma fine from a from this is in the function obtener_oplataforma_usuarios and is fine but I do not how to read this variable from the other function.
you lose minuses (-) in pointers :)
$data['records'] = $this>usuarios_model>obtener_plataformas_usuarios($plataforma);
must be:
$data['records'] = $this->usuarios_model->obtener_plataformas_usuarios($plataforma)
You can use a private variable in your class.
Create the variable above your __construct function, private $plataforma
Set the default value in your __construct function
Set and get in your public function using $this->plataforma
Implemented in your code:
private $plataforma;
public function __construct() {
parent::__construct();
$this->plataforma = "";
}
public function obtener_oplataforma_usuarios() {
$this->load->helper('form');
$this->load->model('usuarios_model');
$this->plataforma = $this->input->post('id_plataforma');
$data['records'] = $this>usuarios_model>obtener_plataformas_usuarios($this->plataforma);
$this->load->view('vista_plataforma_usuarios', $data);
}
function grupos($grupo){
$this->load->helper('form');
$this->load->model('usuarios_model');
$data['records'] = $this->usuarios_model->obtener_grupos($this->plataforma, $grupo);
$this->load->view('vista_plataforma_usuarios', $data);
}
I searched the whole Internet and either there is no one mentioning my problem, or I'm stupid, or maybe it's just a bad day for coding.
What's the situation:
controller "source"
model "source"
model "login"
The "login" model is loaded from autoload.php, then in each controller's constructor I have $this->login->check(), which is checking if the user is logged in (obviously). Then in some of the methods I'm using the "source" model to connect to the database.
I tried loading both of the models from the autoload array, I also tried to load them in the way described here, but it's obviously for an old CI version (the thread is from 2008) and I tried all the possible ways I had in my mind.
Anyway, the result is this:
A PHP Error was encountered
Severity: Notice
Message: Undefined property: Source::$login
Filename: controllers/source.php
Line Number: 10
Fatal error: Call to a member function check() on a non-object in ...\application\controllers\source.php on line 10
Any ideas what I'm missing or how to fix it...? I'm stuck for hours and I don't have any ideas what I could do...
Edit 1: here is the code from the "source" controller:
class Source extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->model('login');
$this->login->check();
}
function index() {
// Pagination config, getting records from DB
$this->load->view('templates/layout', $data);
}
function add() {
$this->load->model('source', '', true);
$btn = $this->input->post('btn');
if(isset($btn)) {
// More form validation
if($this->form_validation->run() == TRUE) {
if($btn == "Add") {
// here I am supposed to use the source model...
}
}
}
$data['page'] = 'source_add';
$this->load->view('templates/layout', $data);
}
}
?>
Edit 2: login.php:
<?php
class Login extends CI_Model {
function __construct() {
parent::__construct();
}
function authenticate($username, $password) {
// the login script comes here
}
function logged() {
if($this->session->userdata('logged') == true) {
return true;
} else return false;
}
function check() {
if(!$this->logged()) {
redirect('/authentication');
}
}
}
?>
Conventionally, the classname of Models should end with _model, so it not collides with controllers with the same name, so try changing
class Login extends CI_Model {
to
class Login_model extends CI_Model {
I resolved this issue by utilizing the hooks and turned the login process into a controller, thereby being able to access user information and setting access levels.
First I added the following to the hooks.php file in the config folder
$hook['post_controller_constructor'][] = array('function' => 'check_login','filename' => 'authority.php','filepath' => 'hooks');
Then I have the following functions in a hook file called authority.php
[EDIT]Having reviewed this I am going to change it to a pre_controller_constructor and see if I can remove what seems to be a double page flash on initial construct.[/EDIT]
function check_login(){
$CI =& get_instance();
$is_logged_in = $CI->session->userdata('is_logged_in');
if(!$is_logged_in){
$unauth_pages = array(your unauthorized pages go here);
if(!in_array($CI->router->class,$unauth_pages)){
$CI->session->set_userdata('before_login_url',current_url());
redirect('login');
}
}
}
function check_authority(){
$CI =& get_instance();
if($CI->session->userdata('usergroupID') == 'SUPADMIN'){return;}
$page = $CI->router->class ;
$method = $CI->router->method;
$method = ($method=='index')?'':$method;
$unauth_pages = array(your unauthorized pages go here);
if(in_array($page,$unauth_pages))return;
$user_group = $CI->session->userdata('usergroupID');
$CI->load->model('user_model');
if($user_group == 'ADMIN' || $user_group == 'USER'){
if($CI->session->userdata('timezone') == ''){
date_default_timezone_set('Canada/Pacific');
} else {
date_default_timezone_set($CI->session->userdata('timezone'));
}
}
if( !$CI->user_model->authorized_content($CI->session->userdata('usergroupID'),$page, $method)){
redirect('unauthorized');
}
}
With the above I dont have to worry about checking on each page but instead utilize the ci framework to do the checking for me.. if its not in the unauth page array then it is a page that requires authorization checking.
Hope this works for you.
I followed this tutorial: http://codeigniter.com/wiki/Internationalization_and_the_Template_Parser_Class/
The controller that loads the language is this one:
<?php
class Example extends Controller {
function Example() {
parent::Controller();
# Load libraries
$this->load->library('parser');
# Load language
$this->lang->load('example', 'english');
}
function index() {
# Load variables into the template parser
$data = $this->lang->language;
# Display view
$this->parser->parse('example', $data);
}
}
?>
In order to change the language I have to manually change english to say spanish in the controller.
What's the best way the user can do this from the index.php file (view)?
The best thing to do is have the user select a supported language on some page, set it as a session variable and call it when ever you need to load a language
$language = $this->session->userdata("language");
$this->lang->load("example", $language);
$data = $this->lang->language;
$this->parser->parse("example", $data);
EDITED BELOW
If you're using CodeIgniter and you're new to this, I wouldn't suggest messing with the index.php file.
You want to do it inside your controller by loading a form where they can pick their language and storing it in the session. I'd also suggest autoloading your session library.
The controller:
<?php
class Home extends Controller {
function Home()
{
parent::Controller();
$this->load->library("session");
}
function index()
{
$language = $this->session->userdata("language");
$this->lang->load("example", $language);
$data = $this->lang->language;
$this->parser->parse("example", $data);
}
function set_lang()
{
if( ! $this->form_validation->run())
{
$this->load->view("select_language_form");
}
else
{
$language = $this->input->post('language', TRUE);
$this->session->set_userdata('language', $language);
redirect('home' 'location');
}
}
}