am I doing something wrong to be able to access Methods stored in a model in a view. For Example. My User model has a method that looks like
public function isCustomer(){
if (isset($this->customer_id))
return true;
else return false;
}
When I try to access this in the view I end up with Call to a member function getResults() on a non-object.
View code is something like
#if($user->isCustomer)
Something
#endif
Is the model ONLY for database relationships between models or can I store my own class functions here as well?
The function i listed is one of the basic ones. I have quite a few more complicated functions that I would like to run from my User class but am not sure how, as i end up with the same error each time. Should they be stored in the controller?
You can store class functions there. By first glance it looks like your missing () on isCustomer. If it were me I would store that in the controller, like:
$customer = $user->isCustomer();
then pass that to the view.
Related
Now I get some model with all properties filled except one.
So I want to make a search in a database and see if there is some registry that matches all the properties values, in which case, get the last property value and keep it.
Now im doing a query wit query builder, giving it all where like this:
$query->Model::select()->where(field, $instance->field);
$query->where(field2, $instance->field2);
...
$query->get();
But I want to know if there some way to make a shortcut like...
$instance->get();
Yes you can do this by defining method in your model like this
class YourModel extends Model
{
public function getFiltered()
{
return Model::where('field1',$this->field1)->where('field2',$this->field2)->get();
}
}
And you can access it like this:
$instance->getFiltered();
You cannot keep function name 'get' because It's already being used in Model which is being extended. But you can change from getFiltered to anything which is not used. Like If the Model was User and the function getFiltered gives user's comments then It can be comments.
I'm using the MVC pattern in my application.
Now I need the view object in a model.
I don't want to add the view as a parameter for my function in the model (since I need it in other functions as well). And I don't want to keep on passing it.
Should a add the view as an attribute for the constructor of the model?
Is there another way? Shouldn't I be needing the view object in the model in the first place?
What would be the preferred way of doing it?
Example:
Controller
function someAction()
{
$somemodel->add();
}
Model
class SomeModel()
{
function add()
{
if ($view->user) {
// do stuff
$this->mail();
} else {
// do other stuff
}
}
function mail()
{
Mailer::send($view->user->email, $this->getitems(), $view->layout);
}
function getitems()
{
return Items::getitems($view->user);
}
}
If you're really doing MVC, then you won't need the view in the model, because only the controller should have access to the view.
Looking at the code you've provided, I can tell one thing: the add() method should not reference $view in any way (even for accessing its properties). Instead, the model should be provided with the $view->user value from the controller. The same goes for the mail() method.
Consider fixing those issues. Otherwise, you'll get into something worse later on.
The model should be separate from the view. So, as mkArtak said, the controller should be the only thing that communicates with the view. Which then passes only the necessary information to the model.
As for the model, it should really only deal with the information that it understands.
i.e. if you had a Car model... you don't want to build it dependent on it's factory. If you did, you would have to change your code if you wanted to build it in different factory.
The controller is where you 'bake' everything prepare for render. By bake I mean you consider any passed in $_REQUEST params, make model API calls to get the data you need, and set template variables to be rendered. Your action, at the end of this process should make a call to a template (view) you choose in order to render the 'baked' template variables.
I am very new to CakePHP and I was just wondering if someone could help me with a couple of things.
I have a User class and an Image class.
In my users_controller.php I have the following functions
function beforeFilter(){
$this->userOb = $this->User->find();
}
function beforeRender(){
$this->set('userOb', $this->userOb);
}
This works fine and I can view the object in my view, with all the correct relations to the Image class.
But doing this overwrites the beforeFilter() and beforeRender() functions in my app_controller.php, so I try and move this functionality to my app_controller.php but I get an error (Undefined property: PagesController::$User)
Also,
$this->Auth->user();
doesn't seem to have the full object map that
$this->User->find();
returns.
So, I guess my question is how can I create a variable that is acessable in all my views, i.e it's defined in app_controller.php, that contains the current logged in Users Object and it's relations.
Thanks.
If the issue is your parent methods are being overwritten by child methods, simply call the parent method in the child, see below:
function beforeFilter(){
parent::beforeFilter();
$this->userOb = $this->User->find();
}
function beforeRender(){
parent::beforeRender();
$this->set('userOb', $this->userOb);
}
put your find result in SessionComponent so you don't have to perform a query for each request (and set variable in beforeRender). In the view you can access it with SessionHelper. $this->Auth->user(); only have the User record.
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 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.