I'm trying to write some classes which pull my data out of my database and create objects based on that data. I'm working with CodeIgniter.
The problem is that if an id is supplied to the __construct method but no row in the database table has that id, an object is returned but with all the properties set to NULL.
Is there a way that I can check this and return NULL instead of an object if there is no corresponding row?
class JS_Model extends CI_Model
{
protected $database_table_name;
protected $database_keys;
...
public function __construct($id = NULL){
if($id){
$this->getFromDatabase($id);
}
}
...
function getFromDatabase($id){
foreach($this->database_keys as $key){
$this->db->select($key);
}
$this->db->from($this->database_table_name);
$this->db->where('id', $id);
$this->db->limit(1);
$q = $this->db->get();
if ($q->num_rows() > 0){
foreach($q->result() as $property){
foreach($property as $key => $value){
$this->$key = $value;
}
}
} else {
// NEED TO SET THE OBJECT TO NULL FOR THIS CASE
}
}
...
}
Any help would be appreciated.
This is not possible, once __construct is called, you will receive an object instance.
The correct way to handle this is to throw an Exception from inside the constructor.
class JS_Model extends CI_Model
{
protected $database_table_name;
protected $database_keys;
public function __construct($id = NULL){
if($id){
$row = $this->getFromDatabase($id);
if (!$row) {
throw new Exception('requested row not found');
}
}
}
}
try {
$record = new JS_Model(1);
} catch (Exception $e) {
echo "record could not be found";
}
// from here on out, we can safely assume $record holds a valid record
why dont you make your constructor private and use a method such as GetInstance(); something like this. Syntax may be incorrect as i dont write much php anymore :-(.
class JS_Model extends CI_Model
{
protected $database_table_name;
protected $database_keys;
...
private function __construct($id = NULL){
}
public static function GetInstance($id)
{
$x = new JS_Model($id);
$x->getFromDatabase($id);
if(is_object($x))
{
return $x;
}
return null;
}
...
function getFromDatabase($id){
foreach($this->database_keys as $key){
$this->db->select($key);
}
$this->db->from($this->database_table_name);
$this->db->where('id', $id);
$this->db->limit(1);
$q = $this->db->get();
if ($q->num_rows() > 0){
foreach($q->result() as $property){
foreach($property as $key => $value){
$this->$key = $value;
}
}
} else {
return null;
}
}
...
}
Related
This is the error which i am getting
I am trying to fetch an array in codeignitor but it is giving me this error:
<?php
foreach($name as $object)
{
echo $object->name . '<br/>';
}
?>
And my Controller code is
public function index()
{
$this->home();
}
public function home()
{
$this->load->model('model_users');
$data['title'] ='First MVC tutorial';
$data['page_header'] ='Intro to MVC';
$data['name'] = $this->model_users->getNames();
$data['users'] = $this->model_users->getUsers();
$this->load->view('welcome_message',$data);
}
This is the model
class Model_users extends CI_Model {
function _construct()
{
parent::_construct();
}
function getNames()
{
$query = $this->db->query('SELECT name from users');
if($query->num_rows>0){
return $query ->result();
}
else{
return NULL;
}
}
function getUsers()
{
$query = $this->db->query('SELECT * from users');
if($query->num_rows>0){
return $query->result();
}
else{
return NULL;
}
}
So can anyone help me solve this error??
As i am new to new to codeignitor
Thanks in advance.
This is the screenshot of my table
Do you have any rows in your users table?
It seems that your model returns null, and foreach expects an Array as it's array_expression var. Could be an empty array as well.
So you might wan't to change the
return NULL;
to
return [];
in your model and that should at least prevent the error.
p.s.
http://php.net/manual/en/control-structures.foreach.php
User::updatemain($set, $where);
This gives Fatal error: Using $this when not in object context
My user class extends from Dbase class and here is user class function:
public static function activate($set, $where) {
return $this->updatemain($set, $where);
here is dbase class (some part of):
private function query($sql = null, $params = null) {
if (!empty($sql)) {
$this->_last_statement = $sql;
if ($this->_db_object == null) {
$this->connect();
}
try {
$statement = $this->_db_object->prepare($sql, $this->_driver_options);
$params = Helper::makeArray($params);
$x = 1;
if (count($params)) {
foreach ($params as $param) {
$statement->bindValue($x, $param);
$x++;
}
}
if (!$statement->execute() || $statement->errorCode() != '0000') {
$error = $statement->errorInfo();
throw new PDOException("Database error {$error[0]} : {$error[2]}, driver error code is {$error[1]}");
exit;
}
//echo $sql;
return $statement;
} catch (PDOException $e) {
echo $this->formatException($e);
exit;
}
}
}
public function updatemain($set, $where) {
return $this->query($sql, $params);
}
this is part of Dbase class
You are calling static method so there is no $this in that context.
If you want to call other static method from given class then use self::method() but if you want to call non-static method you've got problem. First you have to create new object.
When you use static methods, you can't use $this inside
public static function activate($set, $where) {
return self::updatemain($set, $where);
}
Or you have to use singelton design
EDIT
Best solution - rewrite your class to one point access to DB object. And create Model classes to DB access. See my example code below:
core AppCore
<?php
class AppCore
{
public static $config = array();
public static $ormInit = false;
public static function init($config)
{
self::$config = array_merge(self::$config, $config);
}
public static function db($table)
{
// ORM - see http://idiorm.readthedocs.org/en/latest
if (!self::$ormInit) {
ORM::configure(self::$config['db']['connection']);
ORM::configure('username', self::$config['db']['username']);
ORM::configure('password', self::$config['db']['password']);
self::$ormInit = true;
}
return ORM::for_table($table);
}
}
User model
<?php
class UserModel
{
const TABLE = 'user';
public static function findById($u_id)
{
$result = AppCore::db(self::TABLE)->where('u_id', $u_id)->find_one();
return $result ? $result->as_array() : null;
}
}
AppCore init section
AppCore::init(array(
'db' => array(
'connection' => "mysql:dbname={$db};host={$host}",
'username' => $user,
'password' => $pass
),
));
i hope it help make your code better
I'm getting a class not found error but without the name of the class. I got the code from here
but when I try to run it, it gives the following error..
Fatal error: Class '' not found in C:\Program Files\Apache Software Foundation\Apache24\Apache24\htdocs\framework\library\controller.class.php on line 16
and the following is the controller
<?php
class Controller {
protected $_model;
protected $_controller;
protected $_action;
protected $_template;
function __construct($model, $controller, $action) {
$this->_controller = $controller;
$this->_action = $action;
$this->_model = $model;
include 'model.class.php';//other similar posts suggested this but its not working
$this->$model = new $model;
$this->_template = new Template($controller,$action);
}
function set($name,$value) {
$this->_template->set($name,$value);
}
function __destruct() {
$this->_template->render();
}
}
I'm assuming its the model class which is not being found. The model class code is
<?php
class Model extends SQLQuery {
protected $_model;
function __construct() {
$this->connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
$this->_model = get_class($this);
$this->_table = strtolower($this->_model)."s";
}
function __destruct() {
}
}
and sqlquery class is
<?php
class SQLQuery {
protected $_dbHandle;
protected $_result;
/** Connects to database **/
function connect($address, $account, $pwd, $name) {
$this->_dbHandle = #mysql_connect($address, $account, $pwd);
if ($this->_dbHandle != 0) {
if (mysql_select_db($name, $this->_dbHandle)) {
return 1;
}
else {
return 0;
}
}
else {
return 0;
}
}
/** Disconnects from database **/
function disconnect() {
if (#mysql_close($this->_dbHandle) != 0) {
return 1;
} else {
return 0;
}
}
function selectAll() {
$query = 'select * from `'.$this->_table.'`';
return $this->query($query);
}
function select($id) {
$query = 'select * from `'.$this->_table.'` where `id` = \''.mysql_real_escape_string($id).'\'';
return $this->query($query, 1);
}
/** Custom SQL Query **/
function query($query, $singleResult = 0) {
$this->_result = mysql_query($query, $this->_dbHandle);
if (preg_match("/select/i",$query)) {
$result = array();
$table = array();
$field = array();
$tempResults = array();
$numOfFields = mysql_num_fields($this->_result);
for ($i = 0; $i < $numOfFields; ++$i) {
array_push($table,mysql_field_table($this->_result, $i));
array_push($field,mysql_field_name($this->_result, $i));
}
while ($row = mysql_fetch_row($this->_result)) {
for ($i = 0;$i < $numOfFields; ++$i) {
$table[$i] = trim(ucfirst($table[$i]),"s");
$tempResults[$table[$i]][$field[$i]] = $row[$i];
}
if ($singleResult == 1) {
mysql_free_result($this->_result);
return $tempResults;
}
array_push($result,$tempResults);
}
mysql_free_result($this->_result);
return($result);
}
}
/** Get number of rows **/
function getNumRows() {
return mysql_num_rows($this->_result);
}
/** Free resources allocated by a query **/
function freeResult() {
mysql_free_result($this->_result);
}
/** Get error string **/
function getError() {
return mysql_error($this->_dbHandle);
}
}
I'm new to PHP and I'm using PHP 5.5.15. I know I should probably switch this to pdo, but i just want to get this working before gettin jiggy with it.
Any help much appreciated
Simple said, you have this function for your controller:
function __construct($model, $controller, $action) {
$this->$model = new $model;
}
You need to give a $model, wich would be the name of a class. You give no name. This is why class "" can not be found.
If we would write this:
$controller = new Controller("mycrazymodel", null, null);
It means:
function __construct($model, $controller, $action) {
//$this->$model = new $model;
$this->$model = new mycrazymodel; //above means this, if $model = "mycrazymodel"
}
So what does this mean for you?
Locate the call of the Controller::__construct method, which typical mean new Controller(...) and make sure, you give the classname as $model parameter.
Take a look at the manual for further information: http://php.net/manual/en/language.namespaces.dynamic.php
For a small home project I am working on I have been looking for OO design patterns for Memcache implementation, but so far haven't found something I feel fits, so maybe my approach is wrong.
I have a DB connection class and an baseModel class so I want to implement caching on the baseModel where appropriate.
I have implemented the Database connection and the Cacher as Singlton patterns.
I cannot seem to get the Cacher class to read the data or trigger the echo "<p>Getting from cache"; line after I refresh the page on the base Model "loadFromDb" function
Here are the classes:
class Cacher {
protected static $cacher = null;
private static $settings;
public static function getCache() {
if (self::$cacher != null) {
return self::$cacher;
}
try {
self::$settings = parse_ini_file("./configs/main.ini");
self::$cacher = new Memcache();
self::$cacher->connect(
self::$settings['cache_server_host']
, self::$settings['cache_server_port']
);
} catch (Exception $e) {
// TODO log error and mitigate..
echo "Error connecting memcache";
die();
}
var_dump(self::$cacher->getstats());
return self::$cacher;
}
public static function getData($key) {
if (self::$cacher == null) {
self::getCache();
}
return self::$cacher->get($key);
}
public static function setData($key, $data, $expire = 0) {
if (self::$cacher == null) {
self::getCache();
}
if (self::$cacher)
return self::$cacher->set($key, $data, MEMCACHE_COMPRESSED, $expire);
}
}
class ModelBase {
protected $fields = array();
protected $class = null;
function __construct($class_name) {
$this->class = $class_name;
$this->fields = Database::getFields($class_name);
}
public function loadFromDB($id, $fromCache = true) {
$key = "loadFromDB_{$this->class}_{$id}";
if ($fromCache) {
$data = Cacher::getData($key);
if ($data) {
echo "<p>Getting from cache";
return unserialize($data);
} else {
echo "<p>No cache data. going to DB";
}
}
$values = Database::loadByID($this->class, $this->fields[0], $id);
foreach ($values as $key => $val) {
$this->$key = $val;
}
$dataSet = Cacher::setData($key, serialize($this));
echo "<p>Data set = $dataSet";
}
}
Memcache service is running and I can read data directly back if I read the cache directly after I write it, but what I want is to read the data from the DB only the first time the page loads, after that use the cache....
Any comments welcome...
Try doing it like (let the result of the cache decide if you should query the db):
<?php
public function loadFromDB($id) {
$key = "loadFromDB_{$this->class}_{$id}";
//query cache
$data = Cacher::getData($key);
//is it found
if (!empty($data)) {
//echo "<p>Getting from cache";
return unserialize($data);
}
//no so lest query db
else {
//echo "<p>No cache data. going to DB";
$values = Database::loadByID($this->class, $this->fields[0], $id);
foreach ($values as $key => $val) {
$this->$key = $val;
}
//store it in cache
//$dataSet = Cacher::setData($key, serialize($this));
$dataSet = Cacher::setData($key, serialize($values));//<<store the db result not the class
}
//echo "<p>Data set = $dataSet";
return unserialize($dataSet);
}
?>
So I have a problem I have an array that is passes to setData function
after that I call getE that suppose to return the array but instead I'm getting Null what am I doing wrong?
<?php
class Se {
public $data1;
public function setData(array $data){
if (empty($data)) {
throw new InvalidArgumentException('The name of an employee cannot be empty.');
}
$data1 = $data;
$data1 = array_values($data1);
var_dump($data1);
}
public function getE(){
return $data1[0];
}
}
$tmpaaa= array('3333','222');
$ttt = new Se();
$ttt->setData($tmpaaa);
echo $ttt->getE();
So my revised code looks like this now
class Se {
public $data1;
public function setData(array $data)
{
if (empty($data))
{
throw new InvalidArgumentException('The name of an employee cannot be empty.');
}
$this->data1 = $data;
}
public function getE()
{
return $this->$data1[0];
}
};
$tmpaaa= array('3','2');
$ttt = new Se();
$ttt->setData($tmpaaa);
echo $ttt->getE();
?>
In order to access class instance properties from within the class, you need to prefix the variable name with $this. See http://php.net/manual/language.oop5.properties.php
To fix your problem, change this in setData
$data1 = $data;
$data1 = array_values($data1);
var_dump($data1);
to this
$this->data1 = array_values($data);
var_dump($this->data1);
and getE to
public function getE(){
return $this->data1[0];
}
Update
As it appears the $data1 property is required in Se, I'd set it in the constructor, eg
public function __construct(array $data) {
$this->setData($data);
}
and instantiate it with
$ttt = new Se($tmpaaa);
echo $ttt->getE();
It is also recommended not closing the php tag in a class file, this prevents space issues.
<?php
class Se {
public $data1;
public function setData(array $data)
{
if (empty($data))
{
throw new InvalidArgumentException('The name of an employee cannot be empty.');
}
$this->data1 = array_values($data); //you error was here, no need to to assign $data twice so I deleted top line.
}
public function getE()
{
return $this->data1[0];
}
}
$tmpaaa = array('3333','222');
$ttt = new Se();
$ttt->setData($tmpaaa);
echo $ttt->getE();