Fixing Codeigniter Active Record update query - php

This is a class for handling model in Codeigniter app
class MY_Model extends CI_Model {
const DB_TABLE = 'abstract';
const DB_TABLE_PK = 'abstract';
private function update() {
$this->db->update($this::DB_TABLE, $this, $this::DB_TABLE_PK);
}
public function save() {
if (isset($this->{$this::DB_TABLE_PK})) {
$this->update();
}
else {
$this->insert();
}}
And this is a model extended from above class:
class Projects extends MY_Model {
const DB_TABLE = 'projects';
const DB_TABLE_PK = 'project_id';
public $project_id;
public $project_name;
public $project_investment;
public $project_employment;
public $project_province;
public $project_city;
public $project_address;
public $project_estimate;
public $project_duration;
public $project_construction;
}
According to Codeigniter User Guide, i think there is a problem in 3rd parameter of Update query (It just send DB_TABLE_PK name ,in this case 'project_id' ) but since i'm new to OOP , don't know how to fix it .
Codeigniter User Guide :
$this->db->update('mytable', $data, "id = 4");

The function above doe not seem to have the complete WHERE statement for the update()
$this->db->update($this::DB_TABLE, $this, $this::DB_TABLE_PK);
will translate to
UPDATE $this::DB_TABLE SET $this WHERE $this::DB_TABLE_PK
and in your example above $this::DB_TABLE_PK is the name of the key ('project_id'), and not its value.
I would stick with
$this->db->where($this::DB_TABLE_PK, $pk)->update($this::DB_TABLE, $this);
Where $pk is the actual value of your PRIMARY KEY

guide clrearly says
$data_array = array();
$where_array = array();
$this->db->update('table_name', $where_array, $data_array());
so example
$data_array = array('name' => 'Alpha', 'gender' => 'male'); // change column name to "Alpha", and gender column to 'male'
$where_array = array('id' => '4', 'allowed' => '1'); // update row with $data_array where id = 4 and allowed = 1
$this->db->update('person', $where_array, $data_array());
I strongly recommend you to use profiler $this->output->enable_profiler(TRUE); put this anywhere in controller and under your page there will be "profiler" is shows post/get data queries, sessions and all usefull information while developing.

i fixed it :
private function update() {
$value=$this::DB_TABLE_PK;
$this->db->update($this::DB_TABLE, $this, $this::DB_TABLE_PK.' = '.$this->$value);
}

Related

How to dynamically set table name in Eloquent Model

I am new to Laravel. I am trying to use Eloquent Model to access data in DB.
I have tables that shares similarities such as table name.
So I want to use one Model to access several tables in DB like below but without luck.
Is there any way to set table name dynamically?
Any suggestion or advice would be appreciated. Thank you in advance.
Model:
class ProductLog extends Model
{
public $timestamps = false;
public function __construct($type = null) {
parent::__construct();
$this->setTable($type);
}
}
Controller:
public function index($type, $id) {
$productLog = new ProductLog($type);
$contents = $productLog::all();
return response($contents, 200);
}
Solution For those who suffer from same problem:
I was able to change table name by the way #Mahdi Younesi suggested.
And I was able to add where conditions by like below
$productLog = new ProductLog;
$productLog->setTable('LogEmail');
$logInstance = $productLog->where('origin_id', $carrier_id)
->where('origin_type', 2);
The following trait allows for passing on the table name during hydration.
trait BindsDynamically
{
protected $connection = null;
protected $table = null;
public function bind(string $connection, string $table)
{
$this->setConnection($connection);
$this->setTable($table);
}
public function newInstance($attributes = [], $exists = false)
{
// Overridden in order to allow for late table binding.
$model = parent::newInstance($attributes, $exists);
$model->setTable($this->table);
return $model;
}
}
Here is how to use it:
class ProductLog extends Model
{
use BindsDynamically;
}
Call the method on instance like this:
public function index()
{
$productLog = new ProductLog;
$productLog->setTable('anotherTableName');
$productLog->get(); // select * from anotherTableName
$productLog->myTestProp = 'test';
$productLog->save(); // now saves into anotherTableName
}
I created a package for this: Laravel Dynamic Model
Feel free to use it:
https://github.com/laracraft-tech/laravel-dynamic-model
This basically allows you to do something like this:
$foo = App::make(DynamicModel::class, ['table_name' => 'foo']);
$foo->create([
'col1' => 'asdf',
'col2' => 123
]);
$faz = App::make(DynamicModel::class, ['table_name' => 'faz']);
$faz->create([...]);

Codeigniter - Add data to the database

Im trying add data to the database useing CodeIgniter framework. DB method return true, but I have no new data in database.
There is my controller:
class Facebook extends CI_Controller
{
public function index()
{
if($this->input->is_ajax_request())
{
$this->load->model('user_model','user');
$data = array();
$data['u_ip'] = $this->input->ip_address();
$this->user->add_user($data);
}
}
}
And there is my model:
class User_model extends CI_Model
{
public function add_user($data)
{
$this->db->insert('users',$data);
//$res = $this->db->insert('users',$data); (true)
}
}
Update:
There is my database:
id_users (int 255) AI, key
u_ip (varchar 100)
Also, make sure your $data looks like this:
$data = array(
"u_ip" => $this->input->ip_address(),
);
$this->insert("data", $data);
Or if coming from another file, do this:
$this->insert("users", $data[0];)
Remember to load the dataabse:
$this->load->database();
This will go within add_user($data) eg.
class User_model extends CI_Model
{
public function add_user($data)
{
$this->load->database();
$this->db->insert('users',$data);
//$res = $this->db->insert('users',$data); (true)
}
}
However, you can have these automatically, if you go to autoload.php, you can do this:
$autoload['libraries'] = array('database');
And for your model:
$autoload['model'] = array('logic');
You are not mentioning any column names in your query. Try the below code -
class User_model extends CI_Model{
public $db;
public function __construct(){
parent::__construct();
$this->db = $this->load->database('default',true);
}
public function add($data)
{
$data = array(
'title' => 'My title' ,
'name' => 'My Name' ,
'date' => 'My date'
);
$this->db->insert('mytable', $data);
}
$this->input->is_ajax_request()
is this posted via a form ? if so it should be $this->input->post('is_ajax_request');
is_ajax_request being the name of the input your posting,
If its another function within the controller you need to do $this->is_ajax_request();

Default Fields and values in MongoDB, using cakePHP

I am building an application with cakephp 2.1 and mongodb 2.03 , I am using ishikaway's mongodb datasource
I need to set some default values that would be added to a model , I am doing it like so
<?php
class DynamicFormResponse extends AppModel{
public $useDbConfig = 'mongodb';
public $useTable = 'dynamicFormsResponse';
public $primaryKey = '_id';
public $validate=array();
public $mongoschema = array(
'created' => array('type' => 'datetime'),
'modified' => array('type' => 'datetime'),
'escalation'=>array(
'type'=>"integrer",
"default"=>0
),
"status"=>array(
"type"=>"string",
"default"=>"pending"
),
);
public function setSchema($schema) {
$this->_schema=$schema;
}
public function getSchema(){
return $this->_schema;
}
}
Obviously I cannot set default values directly in MongoDb like MySQL, and obviously since I am asking the question the above method is not working.
Any suggestions on how I can solve this ?
Ps:
This did not help CakePHP - Set Default Field Values in the Model
The documentation is not clear either
Full code available here
EDIT:
I have currently solved this problem by committing an MVC sin,
I am adding the default values in the controller before saving the data with the model
<?php
class DynamicFormResponse extends AppModel {
public $name="DynamicFormResponse";
public $useDbConfig = 'mongodb';
public $useTable = 'dynamicFormResponse';
public $primaryKey = '_id';
public $validate = array();
public function getDefaults(){
$defaultValues=array(
"escalation"=>0,
"status"=>"pending",
"department_id"=>NULL,
"user_agent"=>env("HTTP_USER_AGENT")
);
return $defaultValues;
}
...
...
class DynamicFormsController extends AppController {
...
...
public function getForm($id=null){
...
...
/**
* Set defaults values
*/
foreach ($this->DynamicFormResponse->getDefaults() as $fieldName => $defaultValue) {
if (empty($this-> request-> data[$this-> DynamicFormResponse -> alias][$fieldName]))
$this->request->data[$this-> DynamicFormResponse -> alias][$fieldName] = $defaultValue;
}
/**
* Data Validation
*/
if($this->DynamicFormResponse->save($this->request->data) == true ){
$this->set("ticket_id", $this->DynamicFormResponse->id);
$this->render('ticket_successfully_saved');
return;
}
Is there a better solution ? because that seems like a bad way to do it .
it's not really a mongoDB question but anyways, i suggest you to merge your userdata with your default values in beforeSave().
We declare default values in each Model like this:
public $defaultValues = array(
'report' => 't',
'reportinterval' => '7',
'type' => '0'
);
And merge it in beforeSave():
/**
* Extends beforeSave() to add default values
*
* #param array $options
* #return bool
*/
public function beforeSave($options = array()) {
// Add default values if not set already
foreach ($this->defaultValues as $fieldName => $defaultValue) {
if (empty($this->data[$this->alias][$fieldName]))
$this->data[$this->alias][$fieldName] = $defaultValue;
}
return parent::beforeSave($options);
}

How to fetch populated associated models in CakePHP when calling read()

I have the following Models:
class Site extends AppModel {
public $name = "Site";
public $useTable = "site";
public $primaryKey = "id";
public $displayField = 'name';
public $hasMany = array('Item' => array('foreignKey' => 'siteId'));
public function canView($userId, $isAdmin = false) {
if($isAdmin) { return true; }
return array_key_exists($this->id, $allowedSites)!==false;
}
}
and
class Item extends AppModel {
public $name = "Item";
public $useTable = "item";
public $primaryKey = "id";
public $displayField = 'name';
public $belongsTo = array('Site' => array('foreignKey' => 'siteId'));
public function canView($userId, $isAdmin = false) {
// My problem appears to be the next line:
return $this->Site->canView($userId, $isAdmin);
}
}
In my controller I am doing something like this:
$result = $this->Item->read(null, $this->request->id);
// Verify permissions
if(!$this->Item->canView($this->Session->read('userId'), $this->Session->read('isAdmin'))) {
$this->httpCodes(403);
die('Permission denied.');
}
I notice that in Item->canView() $this->data['Site'] is populated with the column data from the site table. But it is merely an array and not an object.
On the other hand $this->Site is a Site object, but it has not been populated with the column data from the site table like $this->data.
What is the proper way to have CakePHP get the associated model as the object (so I can call methods on it) and containing the data? Or am I going about this all wrong?
Thanks!
"...and sets the current model data (Model::$data) with the record found." from http://api13.cakephp.org/class/model#method-Modelread

How can I retrieve data using a model and pass it to be used in a controller using CodeIgniter?

From a user login form i need to use their username ($this->input->post('username')) to query against the membership table in my database so that I can retrieve the users firstname and lastname, which I believe should be done via a model called from my controller. I then need to pass that data back to my controller to use the firstname and lastname to add in to my session userdata which is set in my controller, as shown below.
$data = array(
'username' => $this->input->post('username'),
'firstname' => //need to retrieve value from database,
'lastname' => //need to retrieve value from database,
'is_logged_in' => true
);
$this->session->set_userdata($data);
Thanks,
Kristan.
In your model, make a function to retrieve the first and last name of a user:
public function get_user_details($username){
// retrieve contents from db:
// the first username here is the name of the column in your table
$query = $this->db->select('firstname, lastname')
->where('username', $username)
->get('membership');
return $query->result_array();
}
In your controller, like you were doijng, grab the POST contents in your controller:
$username = $this->input->post('username');
Then, from your controller, call your model function but save the output of that model function in a variable:
$data = $this->user_model->get_user_details($username);
After that, you can do what you were trying to do:
$this->session->set_userdata($data);
Hope that helps. I wrote this from the top of my head but it should work. I also suggest you read the CI documentation through because it really is some of the best documentation I have ever seen for a framework. Good luck.
Please check CodeIgniter user guide for model. The example of Blog controller and Blog model will answer you.
class Blogmodel extends CI_Model {
var $title = '';
var $content = '';
var $date = '';
function __construct()
{
// Call the Model constructor
parent::__construct();
}
function get_last_ten_entries()
{
$query = $this->db->get('entries', 10);
return $query->result();
}
function insert_entry()
{
$this->title = $_POST['title']; // please read the below note
$this->content = $_POST['content'];
$this->date = time();
$this->db->insert('entries', $this);
}
function update_entry()
{
$this->title = $_POST['title'];
$this->content = $_POST['content'];
$this->date = time();
$this->db->update('entries', $this, array('id' => $_POST['id']));
}
}
class Blog_controller extends CI_Controller {
function blog()
{
$this->load->model('Blog');
$data['query'] = $this->Blog->get_last_ten_entries();
$this->load->view('blog', $data);
}
}
You first need to create a model.
class Membership_model extends CI_Model {
function __construct() {
parent::__construct();
}
function getUser($username) {
$query = $this->db->get_where('membership', array('username' => $username));
return $query->result_array();
}
}
then in your controller, use the membership model to retrieve data. Calling this function: $this->membership_model->getUser($this->input->post('username'));

Categories