how to pass a value to model function in code igniter - codeigniter

I want to pass a user id value in variable $userID, to a function in a Model class Clientmodel. The function is get_username(), now in a model do I have to define that function to accept a variable as a parameter? so.. get_username($userID)? Just want to know how is the recommended way in code igniter?
Thanks!
tariq

That really depends on what you use the model for. Most of the time, it will make sense to have a parameter to the method and use that every time:
// Model
function get_username($userID)
{
// do something with $userID
}
// Controller
$this->some_model->get_username($some_id);
On the other hand, sometimes it makes sense for the Model to be "stateful" -- do you have one userID per controller? Will it ever be more than one? Do you need the userID in a large number of methods of that model? Then maybe this will make sense instead:
// Model
function set_userid($userID)
{
$this->userID = $userID;
}
function get_username()
{
// do something with $this->userID
}
// Controller
$this->some_model->set_userid( $some_id );
$this->some_model->get_username();
Other times, you may have one userID which you plan on using over and over, but sometimes you need to use another value, that is when default arguments come into play:
// Model
function set_userid($userID)
{
$this->userID = $userID;
}
function get_username( $userID = NULL )
{
if( $userID === NULL ) $userID = $this->userID;
// do something with $userID (not $this->userID)
}
// Controller
$this->some_model->set_userid( $some_id );
$this->some_model->get_username();

The solution is not Codeigniter specific in any way, it's just basic PHP. Your model is a class, and get_username() is a function that takes arguments.
The most basic way to do it is this:
// Model
function get_username($userID)
{
// do something with $userID
}
// Controller
$this->some_model->get_username($some_id);
Make sure you read about default arguments so you can decide what to do if $userID is not passed (you may not need a default here though), and make sure you check that the value is valid.

Related

How to compare two objects and get different columns in Laravel

I have two objects of the same record which I am getting from the database. One is before the update, and the other is after the update. I want to know the column values which are changed during this update query.
$before_update = DeliveryRun::find($id);
$before_update->name = $request->input('name');
$before_update->save();
$after_update = DeliveryRun::find($id);
compare($before_update, $after_update)
I would define a method on your DeliveryRun model which can be used to compare objects of the same type.
Lets say we want to be able to do something like $deliveryRun->compareTo($otherDeliveryRun). That seems like a nice fluid syntax and reads well in my opinion.
What we want to do is get the attributes and their values for the DeliveryRun we're calling compareTo on and then compare them against the attributes and values for the DeliveryRun we provide as an arguement to the compareTo method.
class DeliveryRun extends Model
{
public function compareTo(DeliveryRun $other)
{
$attributes = collect($this->getAttributes())
->map(function ($attribute, $key) use ($other) {
if ($attribute != $other->$key) {
return $key = $attribute;
}
})->reject(function ($attribute, $key) {
return !$attribute || in_array($key, ['id', 'created_at', 'updated_at']);
});
return $attributes;
}
}
The above gets the attributes for the current ($this) DeliveryRun, converts the array returned from getAttributes() to a collection so we can use the map() function and then loops over each attribute on the DeliveryRun model comparing the key and value of each against the $other DeliveryRun model provided.
The reject() call is used to remove attributes which are the same and some attribute keys which you might not be interested in leaving you just the attributes that have changed.
Update
I am saving object in other variable before update $before_update = $delivery_run; but after update $before_update variable I also gets updated
If I am understanding you correctly, you're still comparing the same object to itself. Try something like the following.
$before = clone $delivery_run; // use clone to force a copy
$delivery_run->name = 'something';
$delivery_run->save();
$difference = $before->compareTo($delivery_run);
I would consider using getChanges() as suggested by #Clément Baconnier if all you're doing is looking to get the changes of an object straight after the object has been saved/updated.

Populating $attributes with values from the previous model?

I've got a Laravel project (actually a Laravel Nova project) that involves entering a lot of data. To save some time I'd like to pre-fill some of the fields in my form, based on the logged in user's last entry.
I can pre-fill fields via the $attributes variable on my model, called Product, like so:
protected $attributes = [
'category' => 'ABC'
];
And I can do this for more dynamic data in the constructor like so:
function __construct() {
$this->attributes['category'] = Str::random();
parent::__construct();
}
But I'm not quite sure how I'd go about this when I want to retrieve what the user entered last time. For example, I'd like to do this:
function __construct() {
$user = auth()->user()->id;
$last = Product::where('created_by', $user)->latest()->first();
$this->attributes['category'] = $last['category'] ?? null;
}
However that ends up in an infinite loop. Same if I call $this->where('created_by' ...
Is there a way I can set $attributes of a new Product based on the last Product created by the user?
Nova fields have resolveUsing method, so in your case if you want to populate Text field:
Text::make('Category')->resolveUsing(function () {
return optional(auth()->user()->products()->latest()->first())->category;
})
I found the solution in the Nova Defaultable package.
Once you add the necessary traits, you can just add ->defaultLast() to a resource field and it'll default to the last set value. This also works for relationships which is perfect for my use case.

Set custom date field when new record created in Laravel

I want to be able to save a "followup date" for a student when a new student is created. This followup date needs to be 2 weeks in the future.
I have managed to do this in the controller as follows:
public function store(StudentRequest $request)
{
$data = $request->all();
$data['followup'] = Carbon::now()->addWeeks(2);
$student = Student::create($data);
// ....
}
However, this feels like a very long-winded way of doing things. I feel as though there ought to be a way to do it automatically on the Model with less code. I thought about using a Mutator, but that wouldn't work because the 'followup' field isn't actually being set from anywhere.
You can extend the save function in your model like this:
...
public function save(array $options = []) {
if(!$this->exists){ # only before creating
$this->attributes['followup'] = Carbon::now()->addWeeks(2);
}
return parent::save($options);
}
...

codeigniter pass variable from controller to model

simple issue I presume.
My controller is getting the if to display from the url using $this->uri->segment(3). This will always be a single value. I am putting this in an array to pass to the model with:
$customerid = array(
'id' => $this->uri->segment(3)
);
The controller syntax is below:
function confirm_delete_customer()
{
$data['title']="Confirm Customer Deletion";
$customerid=array(
'id'=>$this->uri->segment(3)
);
//query model to get data results for form
$data=array();
if($query=$this->model_master_data->get_customer_records_to_delete()){
$data['records']=$query;
$this->load->view("master_data/view_master_data_header",$data);
$this->load->view("master_data/view_master_data_nav");
$this->load->view("master_data/view_content_master_data_confirm_customer_deletion",$data);
$this->load->view("master_data/view_master_data_footer");
}
I am then trying to access this array value and pass it to my model to process. If I hard code the array into the model it works as per below syntax:
Model - Manual Syntax is:
function get_customer_records_to_delete()
{
$query = $this->db->get_where('customers', array('id'=>43));
return $query->result();
}
if I try replace this with the array from my controller it fails with error:
Undefined variable: customerid
idea of model that I want to get working:
function get_customer_records_to_delete()
{
$query = $this->db->get_where('customers', $customerid);
return $query->result();
}
I have a feeling it is something small. however is this the best way to get a single record from the database in order to output to a view?
Thanks in advance for the assistance.
The best way to do that is:
function confirm_delete_customer()
{
$data=array();
$data['title']="Confirm Customer Deletion";
$customerId = $this->uri->segment(3);
//Prevent SQL injections
if(!is_numeric($customerId) || empty($customerId)) {
show_error("Bad Request");
}
$query = $this->model_master_data->get_customer_records_to_delete($customerId);
if ($query){
$data['records']=$query;
$this->load->view("master_data/view_master_data_header",$data);
$this->load->view("master_data/view_master_data_nav");
$this->load->view("master_data/view_content_master_data_confirm_customer_deletion",$data);
$this->load->view("master_data/view_master_data_footer");
}
}
and then you can simply call:
function get_customer_records_to_delete($customerId)
{
$query = $this->db->get_where('customers', array('id'=>$customerId));
return $query->result();
}
at your model.
You need to pass the value as an argument to the function so it can access it.
Ex:
get_customer_records_to_delete($customerid)
{
// now $customerid is accessible
$query = ....;
return $……;
}
You should heavily rely on function parameters. Grab the customer id from the controller and send it to the model. Moreover, you can use row() to get a single result from the database.
Controller:
function confirm_delete_customer(){
$data['title']="Confirm Customer Deletion";
$customerid=$this->uri->segment(3);
//query model to get data results for form
$data=array();
if($query=$this->model_master_data->get_customer_records_to_delete( $customerid)) //you are sending customer id as a parameter here
$data['records']=$query;
$this->load->view("master_data/view_master_data_header",$data);
$this->load->view("master_data/view_master_data_nav");
$this->load->view("master_data/view_content_master_data_confirm_customer_deletion",$data);
$this->load->view("master_data/view_master_data_footer");
}}
Model
function get_customer_records_to_delete($customerid)
{
$query = $this->db->get_where('customers', array("id"=>$customerid)); //you are using the customer id sent from the controller here
return $query->row(); //this will return a single row
}
Old thread but the answer is to declare the variable as "public" in the controller (i.e. public $customerid;), in which case it'll be available to your model. In some cases it's probably safer to explicitly pass as an argument. However, when you have several variables, it's useful to have the option to declare them instead.

Code Igniter Models & libraries

in CI i created a model called "User" which has a method called "entries" and another one called "books"
I would like to pass a $user_id parameter to the model so it creates an instance of the class in my controller.
the way I currently call the model in the controller is :
$data1 = $this->user->entries($user_id);
$data2 = $this->user->books($user_id);
I would like to pass that user_id parameter directly to the constructor so that i dont have to use the $user_id parameter each time
perhaps something like this ( i know the syntax is wrong in this case):
$this->load->model('user',$user_id);
$data['row1'] = $this->user->entries();
$data['row2'] = $this->user->books();
Please forgive my lack of understand of OOP ..i just made the switch.
thanks for your help
You cannot pass variables to the constructor, but you could make a method to set the userID, and then use it.
Example:
class user extends CI_Model{
var $user_id;
function __construct(){
parent::__construct();
}
function set_user_id($user_id){
$this->$user_id = $user_id;
}
}
And then inside your entries and books books method, you can use $this->$user_id, without needing to pass it again.
Like so:
function entries(){
$user_id = $this->user_id;
}

Resources