What I have is a product class, you can get a product via its id or its product nr. So I have created 2 constructors. The class is retrieving the product via the database and mapping the result to the class variables.
class Partnumber extends CI_Model
{
private $partNr;
private $description;
private $type;
public function __construct() {
}
public static function withId( $id ) {
$instance = new self();
$instance->loadByID( $id );
return $instance;
}
public static function withNr($partnumber) {
$instance = new self();
$instance->getIdFromPartnumber($partnumber);
return $instance;
}
protected function loadByID( $id ) {
$instance = new self();
$instance->getPartnumberFromId($id);
return $instance;
}
private function getIdFromPartnumber($partnumber){
$this->db->select("*");
$this->db->from('part_list');
$this->db->where('part_number', $partnumber);
$query = $this->db->get();
return $query->result_object();
}
//get the partnumber from an part id
private function getPartnumberFromId($partId){
$this->db->select("*");
$this->db->from('part_list');
$this->db->where('id', $partId);
$query = $this->db->get();
$this->mapToObject($query->result());
}
private function mapToObject($result){
$this->partNr = $result[0]->Part_number;
$this->description = $result[0]->Description;
$this->type = $result[0]->Type;
}
public function toJson(){
return json_encode($this->partNr);
}
}
The mapping works, (I know, I have to catch the errors). But all the values are null when I calling the toJson method.
I call it like this:
class TestController extends MX_Controller{
public function __construct(){
parent::__construct();
$this->load->model('Partnumber');
}
public function loadPage() {
$p = Partnumber::withId(1);
echo $p->toJson();
}
}
And yes, I know for sure that data is coming back, because I can print all the items in the mapping method. But why is the data gone when I acces it via toJson?
Your method withId calls loadByID which creates a new instance of your model. It does not load the data into the model that was created in withId which is returned
Related
I wrote a class
class User {
private $cars = array(); //store class Car 's object
public function getCars()
{
return $this->cars;
}
public function setCars($cars)
{
$this->cars = $cars;
}
}
class Car{
private $model;
public function getModel()
{
return $this->model;
}
public function setModel($model)
{
$this->model = $model;
}
}
$user = new User();
$cars = $user->getCars();
$cars[0]->getModel();
When I try to access getModel() php report "Call to undefined method stdClass::getModel()" .
Is there the best practice to deal with such case?
Edit:I filled the getter and setter. In fact, It's generated by phpstorm.
Edit:I tried again and it works well with the demo code below. The original code is too complicated to show. Maybe I caused by my misunderstanding of copying by value and by reference of array.
Please ignore this question. sorry.
class User {
private $cars = array(); //store class Car 's object
public function getCars()
{
return $this->cars;
}
public function setCars($cars)
{
$this->cars = $cars;
}
}
class Car{
private $model;
public function getModel()
{
return $this->model;
}
public function setModel($model)
{
$this->model = $model;
}
}
$user = new User();
$car = new Car();
$car->setModel("Ford");
$arr = $user->getCars();
array_push($arr,$car);
$user->setCars($arr);
foreach($user->getCars() as $car) {
var_dump($car->getModel());
}
You haven't shown your [Getter Setter ] code. You need to create one with something like:
public function setCars($val){
$this->cars = $val;
}
public function getCars(){
return $this->cars;
}
The same applies for getModel()
I am trying to understand how to efficiently create a new class object and set the variables directly.
I have a class:
class element_model
{
public $sType;
public $properties;
}
I have a controller in which the following function is defined:
public function create_element($sType, $properties)
{
$oElement_model = new element_model($sType, $properties);
return new element_model($sType, $properties);
}
But this does not returns a new element_model with properties set, it just returns an empty object.
It does not, however, throw an error.
What is the reason the function above does not work?
You have to pass to the constructor of the class, in PHP you should have a method in the class __construct :
class element_model
{
public $sType;
public $properties;
public function __construct($type, $property)
{
$this->sType = $type;
$this->properties = $property;
}
}
Then you can access them (note the variables are public)
$elem = new element_model($sType, $properties);
$elem->sType;
Although in some cases it is better to encapsulate vars (declare them private):
class element_model
{
private $sType;
private $properties;
public function __construct($type, $property)
{
$this->sType = $type;
$this->properties = $property;
}
public function getType()
{
return $this->sType;
}
public function getProperty()
{
return $this->properties;
}
}
Then you can access the variable through a getter
$elem = new element_model($sType, $properties);
$elem->getType(); //and
$elem->getProperty();
You must create a __construct function in your class that accepts the parameters and sets your variables. Like this:
class element_model{
.
.
.
public function __construct($type,$properties)
{
$this->sType = $type;
$this->properties = $properties;
}
}
The __construct function will be called when you create the object.
But if you want to be extra cool in programming, just define your properties as private and create getter and setter functions to access the variables of your object
private $sType;
public function getSType(){
return $this->sType;
}
public function setSType($value){
$this->sType = $value;
}
I want to build class that implement a lot of methods based on it's id,
so I want to have one class parent that implement the methods!
and when i want to use this class I will extend it and just override the id variable :
class parent
{
$id = "parent";
private __construct()
{
}
public static function create_instance()
{
$instance = new self();
return $instance;
}
public static function print_id()
{
echo $this->id;
}
}
class child extend parent
{
$id = "child";
}
$instance = child::create_instance();
$instance->print_id();
the result will be "parent", but I want the result to be child ?
How to do that ?
EDIT : I also tried this and got parent instead of child:
class parent1 {
private $id = "parent";
public function __construct() {
}
public static function create_instance() {
$instance = new static ();
return $instance;
}
public function print_id() {
echo $this->id;
}
}
class child extends parent1 {
private $id = "child";
}
$instance = child::create_instance ();
$instance->print_id ();
The problem is that the visibility of $id is private whereas it should be protected because print_id() is only defined on the parent; as such it can only reach its own $id.
class parent1 {
protected $id = "parent";
// ...
}
class child extends parent1 {
protected $id = "child";
}
The alternative is, of course, to override print_id() in the child class.
Currently when you call create_instance method on child class as a result instance of parent class is created not child class as you expect.
Use late static binding in parent class "create_instance" method:
public static function create_instance()
{
$instance = new static();
return $instance;
}
More details http://php.net/manual/en/language.oop5.late-static-bindings.php
I think code given below works fine (I am busy on learning OOP PHP and not tested these code yet) if I want to retrieve single record. What if I want to loop the record ? How to do that ? Can I use single class to retrieve single and loop record ? If yes how ?
include('class.database.php');
class News
{
protected $id;
protected $title;
protected $detail;
protected $updatedon;
protected $views;
protected $pic;
protected $cat;
protected $reporter;
function __construct ($id);
$newsdb = new Database;
$Query = "SELECT * FROM news WHERE nws_sn =".$id;
$db->query($Query);
$db->singleRecord();
$this->id = $newsdb->Record['nws_sn'];
$this->title = $newsdb->Record['nws_title'];
$this->detail = $newsdb->Record['nws_detail'];
$this->updatedon = $newsdb->Record['nws_time'];
$this->views = $newsdb->Record['nws_view'];
$this->pic = $newsdb->Record['nws_pic'];
$this->cat = $newsdb->Record['nws_cat_id'];
$this->reporter = $newsdb->Record['nws_rptr_id']
}
function getId () {
return $this->id;
}
function getTitle () {
return $this->title;
}
function getDetail () {
return $this->detail;
}
function getViews () {
return $this->views;
}
function getImage () {
return $this->pic;
}
function getTime () {
return $this->updatedon;
}
}
You want to use a constructor to initialize an internal state of your object. In your case you do too much in your constructor which also breaks "single responsibility principle". It seems that "News" is just an entity or data transfer object, so you have to initialize it from outside.
First, I would keep News just to store information received from database.
Second, I would create a static factory method inside News class so it create an actual News object and populate it with data passed to the method from outside. Alternatively, you could create a factory object to create your entity, but since the construction logic is simple enough, I thought it makes sense to keep it inside a single method.
Consider the code below:
class News
{
protected $id;
protected $title;
protected $detail;
protected $updatedon;
protected $views;
protected $pic;
protected $cat;
protected $reporter;
public static createFromRecord($record)
{
$obj = new self();
$obj->setId($record->Record['nws_sn']);
$obj->setTitle($record->Record['nws_title']);
$obj->setDetail($record->Record['nws_detail']);
$obj->setUpdateon($record->Record['nws_time']);
$obj->setViews($record->Record['nws_view']);
$obj->setPic($record->Record['nws_pic']);
$obj->setCat($record->Record['nws_cat_id']);
$obj->setReporter($record->Record['nws_rptr_id']);
return $obj;
}
function getId () {
return $this->id;
}
function getTitle () {
return $this->title;
}
function getDetail () {
return $this->detail;
}
function getViews () {
return $this->views;
}
function getImage () {
return $this->pic;
}
function getTime () {
return $this->updatedon;
}
// ... add public setters for the properties
}
...
$newsdb = new Database;
$Query = "SELECT * FROM news WHERE nws_sn =".$id;
$db->query($Query);
$record = $db->singleRecord();
$newsObject = News::createFromRecord($record);
I wrote a class for module creating. That run correctly except that model object.
Model class :
class Model{
public static $db;
protected $_table_name;
public function __construct() {
self::$db =& DB::singleton();
}
public function get($rows="*",$where=null,$page_no=null,$limit=null,$order_by=null,$table_name=null){
if(!isset($table_name)||empty($table_name)){
self::$db->table=$this->_table_name;
}else{
self::$db->table=$table_name;
}
self::$db->rows = $rows;
self::$db->limit=$limit;
self::$db->where=$where;
self::$db->page_no=$page_no;
self::$db->order_by=$order_by;
return self::$db->read();
}
public function delete($id,$table){
self::$db->table = $table;
self::$db->where ="id='{$id}'";
self::$db->delete();
return 1;
}
public function drop_table($table){
self::$db->table=$table;
self::$db->drop_table();
return 1;
}
public function get_module_name(){
return $this->_table_name;
}
public function set_table($table_name){
$this->_table_name=$table_name;
}
}
Extended class :
class m_publication_categories extends model
{
protected $_table_name = 'publication_categories';
}
Controller :
class Controller{
public $db;
public $model;
public function __construct(){
core::$theme->setup();
$model_class_name = "m_".get_called_class();
$this->model=new $model_class_name();
}
public function listAction(){
$module_name = $this->model->get_module_name();
$module_model = new m_modules();
/**moduleinfo*/
$module = $module_model->get("*","table_name='{$module_name}'");
$module = $module[0];
$module_columns = $module_model->list_fields($module->id);
$data = $this->model->get();
print_r($data);die;
$this->assign('data',$data);
$this->assign('module_columns' , $module_columns);
$this->assign('module',$module);
$this->display('list_module_data','modules');
}
}
I want use model::get method from controller $this->model->get but that not work correctly. But if i print_r $this->model in controller , return result like that :
m_publication_categories Object ( [_table_name:protected] => publication_categories )
This means code in extends model class, but why not enter main model class ?
thanks.