I am calling one controller method from another controller's method. I can confirm that the method is being called because when I do a print_r on the passed data, I see everything I expect. My problem is that when I call $this->Log->save($this->data) nothing is written to the DB. I am a .NET developer, hence I know preciously little about cakePHP, but I know that this is the way one is supposed to save stuff to the DB, hence I am majorly stumped.
<?php
//The calling controller
App::import('Controller', 'Logs');
class othAuthComponent extends Object //I noticed this inherits from Object,
//but it doesn't seem to be a problem
{
function SomeFunction()
{
//create instance of our Logs controller as per example
$Logger = new LogsController;
$Logger->constructClasses();
$Logger->cms_addlog($user['User']['name'].' Logged in', $user['User']['id']);
}
}
?>
And the offender:
<?php
//the called controller
class LogsController extends AppController
{
function cms_addlog($note,$ba_id)
{
$this->Log->create();
$curDateTime = getdate();
$this->data['LogTime'] = $curDateTime;
$this->data['Note'] = $note;
$this->data['brandactivatorid'] = $ba_id;
//print_r($this->data);
//die();
$this->Log->save($this->data);
}
}
?>
The correct way to do this is to make the cms_addlog function part of the Log model.
Then call
$this->Log->cms_addlog($user['User']['name'].' Logged in', $user['User']['id']);
You're not supposed to call Controller actions/methods from anywhere in your code. Controller actions are meant to be directly accessed from the browser.
The clean way is to implement a addLog method in your model and call that one either from the controller, or from the component.
Please read http://book.cakephp.org/2.0/en/getting-started/cakephp-structure.html and http://book.cakephp.org/2.0/en/cakephp-overview/understanding-model-view-controller.html for further reference.
Related
Below classes are working fine, trying to learn MVC and I just want to know why. It is probably very simple but I could not understand.
So In controller class I have initiated View object(Defined somewhere else) and assigned to $this->view. Now Why is this not giving me any error as I have not defined the view property anywhere in the controller class neither it is extending.
Same thing with the error class. How come $this->view->msg is working fine as msg property is not defined anywhere neither in parent nor in Error controller itself.
How these are working on the fly.
<?php
class Controller {
function __construct() {
echo 'main controller <br/>';
$this->view = new View();
}
}
?>
Error class extending the controller
<?php
class Error extends Controller {
function __construct() {
parent::__construct();
echo 'This is error mate';
$this->view->msg = 'This page does not exit by msg';
$this->view->render('error/index');
}
}
?>
You can dynamically add properties to objects at any time, they do not need to be declared in advance; just like regular variables if you will. That's all.
The downside is that these properties will be public, which you may not desire, and that it's bad practice because it makes the structure of the class less obvious.
I am performing the jquery POST correctly, however I would like to call another PHP function inside the controller. EDIT The code below works fine....I'm just an idiot. Someone close this please.
Here is the setup:
class controller extends CI_Controller {
function con1() {
//retrieve post variable
$this->con2()
}
function con2() {
//do something
$this->my_model->get_results() //fails
}
}
Jquery POSTS to con1, however it will fail when i do $this->con2(). Is there anyway I can get this to work? Also, is it possible to call a model once jquery posts the data?
Thanks
It's not really clear what you aren't able to do, but why are you juggling with controller's methods, when model are done just for that?
The purpose of a Model is being something re-usable, so why don't you call it right in con1() method?
class Controller extends CI_Controller {
function con1() {
$this->load->model('my_model');
//retrieve post variable
echo $this->my_model->get_results();
}
}
Also, post variable are available to Models also, if you want to grab their values there.
If you expand your answer with further details I'll edit and update my question, so far it's just a bit of a guessing on what's wrong. The code I showed should work, provided the get_result() method actually returns something (which you need to echo out).
If by "how do I call a function within a model" means how you call a model's method inside another model's method, well, it works like any php class method's call, $this->other_method();
Haven't used codeigniter but I suspect redirecting to con2 within con1 with the post array would fix the issue.
Are functions inside of models directly accessible by users?
Can a user pass arguments directly to a function in a model? Or, do arguments have to be passed through php?
In otherwords:
I have a model called notifications and in there a function called get_notifs($user)... I use the controller to call the function like the get_notifs($_SESSION['user_id']) (which is encrypted). I don't want someone to be able to call get_notifs() with anything but their $_session as a argument. What is the best solution?
Am I already okay?
Should I rename get_notifs() to
_get_notifs()?
Should I check the
$_SESSION['user_id'] in the method
itself?
Or, is there another better solution
than any of these?
I have a controller: ajax.php which loads the model notification
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->library('tank_auth');
$this->load->model('notification');
$this->load->model('search');
}
function get_notifs()
{
$me = $this->session->userdata('user_id');
if ($e = $this->notification->get_notif($me))
{
...........
}
else{
echo "nothing was found wtf?";
}
.........................................................
model: notification.php
function get_notifs($user){
......
}
Your code is perfectly fine!
Am I already okay?
I Think so
Should I rename get_notifs() to _get_notifs()?
No, it's a public method so no need to make it look private.
Should I check the $_SESSION['user_id'] in the method itself?
No, this is the controller's job
Or, is there another better solution than any of these?
You only need a solution to a problem, and i don't see a problem here
it sounds liek your application may be used by people other then yourself, i.e the public developers, why would you want enforce developers to code things your way, that's going to make them upset at your application.
CI Only routes requests to a controller, the user cannot access a model or library or any other class, the route goes like so: /controller/method/param
the first segment will only ever load a controller file, the second will call the method in the param, passing any other variables such as param to that method.
Source: http://codeigniter.com/user_guide/overview/appflow.html
As you can see from the flow chart above, only the controller has access to the model's
If you'll only use it while in a session the best way would be this:
function get_notifs(){
if(!isset($_SESSION['user_id'])){
return false;
}
$user = $_SESSION['user_id'];
/* Your code here */
}
There's no point of requiring an argument when you'll only use the function with one specific variable which is also available globaly.
Edit: I don't know why you're using functions in your models. Doesn't make any sense, do you mean methods?
I have a view helper that manages generating thumbnails for images. The images are stored using a unique ID and then linked to a file resource in the database.
I am trying to find out if it is possible for the view helper that generates these images to access the model or controller directly, as it is not possible to load the image data at any other point in the controller work flow.
I know this is a bit of a hack really, but it is easier than trying to rebuild the entire data management stack above the view.
If you had set the data in the model or controller you could access it. So you'd have to think ahead in the controller. As you said you can't load it in the controller, perhaps you need to write a specific controller function, which you can call from the view using $this->requestAction() and pass in the image name or similar as a parameter.
The only disadvantage of this is using requestAction() is frowned upon, as it initiates an entirely new dispatch cycle, which can slow down your app a bit.
The other option, which may work is creating a dynamic element and passing in a parameter into the element and have it create the image for you. Although I'm not too sure how this would work in practise.
How are you generating the thumbnails using the helper in the view if you aren't passing data into it from a controller or model? I mean if it was me, I would be setting the 'database resource' in the controller, and passing it to the view that way, then having the helper deal with it in the view. That way you could bypass this issue entirely :)
$this->params['controller'] will return what you want.
According to the ... you can put this code in a view.ctp file then open the URL to render the debug info:
$cn = get_class($this);
$cm = get_class_methods($cn);
print_r($cm);
die();
You could write a helper and build in a static function setController() and pass the reference in through as a parameter and then store it in a static variable in your helper class:
class FancyHelper extends FormHelper {
static $controller;
public static function setController($controller) {
self::$controller = $controller;
}
... more stuff
}
Then in your Controller class you could import the FancyHelper class and make the static assignment in the beforeFilter function:
App::uses('FancyHelper', 'View/Helper');
class FancyController extends AppController {
public $helpers = array('Fancy');
function beforeFilter() {
FancyHelper::setController($this);
}
... more stuff
}
And then you could access the controller from other public functions inside FancyHelper using self::$controller.
You can check the code(line ☛366 and
line ☛379) of the FormHelper, try with:
echo $this->request->params['controller'];
echo Inflector::underscore($this->viewPath);
I am very new to codeigniter but understand OOP and MVC as I do a lot of Rails development. One thing I haven't figured out yet is how to write a class level method in codeigniter and access it in a controller. For example, I have
<?php
class User_model extends Model {
function user_model()
{
parent::Model();
}
public static function get_total_users_count(){
$results = $this->db->query("SELECT * FROM bhr_users GROUP BY userid");
if($results){
return $results->num_rows();
}
return 0;
}
}
?>
I think what I have done here is established a class level method for my model that I should be able to call with User_model::get_total_users_count() Now in my controller which a previous programmer called "Welcome" I have something like:
<?php
class Welcome extends Controller {
function Welcome()
{
parent::Controller();
$this->load->model('bhr_model');
$this->load->model('user_model');
}
function index()
{
$invite = $this->uri->segment(3);
if($invite == 'invitefriends') {
$pagedata['invitefriends'] = $invite;
} else {
$pagedata['invitefriends'] = '';
}
$pagedata['numberofpeople'] = User_model::get_total_users_count();
$this->load->view('default_page', $pagedata);
}
}
The above method call to get_total_users_count does not work because it says because I am using the db method on a class level function in get_total_users_count. In other words $this has no db method when I reference a class.
So now my question is a bit more theoretical. I always thought that instance methods should only be used when a method is acting on a specific instance of an class. Makes sense, right? However, get_total_users_count is acting on all "users" and counting them. It just seems like that should be a class level method. Do you agree? If do, do you know how I can access the database from withing the framework inside a class level function?
Thanks!
Since you are not instantiating User_model, you must get the CI instance, then use that for your db queries.
Inside get_total_users_count():
$ci_ins =& get_instance();
$ci_ins->db->query();
You can make your class as a helper so it will not be load as a instance. Only the code will be included so you can just call it as:
$sample = class_name::method();
CodeIgnighter works is by instantiating your models as you load them. What Thorpe Obazee said is the correct codeIgnighter way to use your Model.
What you are asking is if you can use a static method as you'd expect in most circumstances, which just isn't how CI works.
To accomplish what you're after, mives points out get_instance() which is the correct way to get at the main CI object. I use that way myself to do what you're doing.
get_total_user_count is more of a function for a user table gateway.
User model should have things like getUsername and getLastLogin.
User Table Gateway should have things like findUserById, createNewUser, and getTotalUserCount
$pagedata['numberofpeople'] = $this->user_model->get_total_users_count();
That's the CI way.