accessing parent class inherited variable in subclass in PHP - php

I have made a class in php which is goind to be inherited by another class in the other folder.
when i put echo $this->protectedvariableofclass; //in subclass function
it gives no value
remember my base class is stored \class\user.php
sublass is stored as \model\model_user.php
Please help me out
Thanks in advance
Base Class in \class\user.php
<?php
class user
{
protected $user_id;
//setter method
public function set_user_id($user_id)
{
$this->user_id=$user_id;
}
//getter method
public function get_user_id()
{
return $this->user_id;
}
}
?>
Subclass in \model\model_user.php
<?php
require_once 'class/user.php';
class model_user extends user
{
public function checkUser()
{
echo $this->user_id;
$sql = "SELECT * FROM user WHERE user_id='$this->user_id'";
$result = mysql_query($sql);
if(!result)
{
die('error'.mysql_error());
}
$duplicates = mysql_num_rows($result);
if($duplicates > 0)
return 1;
else
return 0;
}
}

Maybe you have done this already, but in case you're not, try this:
$model_user = new model_user();
$model_user->set_user_id(5);
$model_user->checkUser(); // Should output 5

Everything I see is that you're trying to output user_id which is not assigned anywhere in the posted code.

Related

Query database, and pass the results to a child class in a separate file

I'm going out of my mind here, and I know I have asked kind of the same question before - but I plan to keep the rest of my hair.
To outline my problem: I have a class that queries the database (QueryDB), and stores the results as an associative array called $data, and another class (DisplayTable) that should display a table based off these results.
I can print_r($data) from within the class itself, but I how do I get access to the $data variable from a child class in a separate file? I have spent the last week trying just about everything - with or without $this->, making getters and setters, returns/no returns, but the array in DisplayTable either comes out empty or just returns NULL.
If I hardcode an array ($defined) in QueryDB that's identical to the results I get from the $data array, I can pass it just fine to the child class using $this->defined, so the only apparent difference between $data and $defined, is that $data is dynamically generated. Are those treated completely different than static ones, or am I missing some basic thing in my parent or child class(es)?
And if you could please briefly explain my error(s) instead of just saying "you need this or that at line X". That doesn't help me to learn, and I really want to get better at this :)
querydb.php:
class QueryDB extends DBCon {
public $q;
public $result;
public $data = array();
public $defined = array(
array(
"id" => 1,
"user" => "user1",
"pass" => "pass1"),
array(
"id" => 2,
"user" => "user2",
"pass" => "pass2")
);
public function __construct($q) {
$result = $this->connect()->query($q) or die("Database error");
$numRows = $result->num_rows;
if ( $numRows > 0 ) {
while ($row = $result->fetch_assoc()) {
$this->data[] = $row;
}
return $this->data;
} else {
echo 'No rows found.';
}
}
}
displaytable.php:
class DisplayTable extends QueryDB {
public function __construct() {
echo '<pre>';
print_r($this->defined); // Returns the hardcoded array
print_r($this->data); // Returns an empty array
echo '</pre>';
}
}
EDIT jan 18: Ok, after fiddling a bit, I suddenly got it to work. Probably not the optimal or correct way of doing it, but my code looks like this now:
querydb.php:
class QueryDB extends DBCon {
public $q;
public $result;
public $data = array();
public function __construct() {
}
public function query($q) {
$result = $this->connect()->query($q) or die("Database error");
$numRows = $result->num_rows;
if ( $numRows > 0 ) {
while ($row = $result->fetch_assoc()) {
$this->data[] = $row;
}
return $this->data;
} else {
echo 'No rows found.';
}
}
}
displaytable.php:
class DisplayTable extends QueryDB {
public $foo;
public function __construct() {
parent::__construct();
}
public function getTable($foo) {
echo '<pre>';
print_r($foo->data);
echo '</pre>';
}
}
index.php:
$res = new QueryDB();
$res->query("SELECT * FROM `testdb`");
$tab = new DisplayTable();
$tab->getTable($res);
Do I understand this correct?:
$res = new QueryDB(); // I instantiate the QueryDB object as $res in index.php
$res->query("SELECT * FROM 'testdb'"); // I pass the query as an argument
In QueryDB class, the $data array gets returned: return $this->data;
$res now holds the $data array, right?
I instantiate the DisplayTable() object as $tab in index.php
I call the getTable() method using $res as argument
The getTable() method takes $foo as an placeholder argument (which in fact is $res)
I now have access to $foo->data / ($res->data)
It's probably too much back and forth, but it's the only solution I can come up with right now. Suggestions to making it simpler (if possible) are still very appreciated :)
If you override the constructor in a class that extends another class, that child constructor runs instead of (rather than in addition to) the parent class constructor. So you (usually) want to explicitly call the parent class constructor from within the child class constructor:
class DisplayTable extends QueryDB {
public function __construct() {
parent::__construct();
// stuff specific to this child class
}
}
That said, constructors shouldn't return anything or echo anything. They should be used only for initializing the object. Don't put the main logic for your class in the constructor, put it in a method called query() or something.

How to use other class methods inside of another class in same file?

I've a scenario where i have to use a Class that extends another class which is not a codeigniter class and inside of the method, i need to call another method to perform Database operation.
How can i achieve?
<?php
require_once(APPPATH.'third_party/OauthPhirehose.php');
class Get extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->model('tweets_model');
}
public function getall()
{
$tags = $this->tags_model->get();
$result = $tags->row();
$first = $result->first_tag;
$second = $result->second_tag;
return array($first, $second);
}
public function insert_raw_tweet($raw_tweet, $tweet_id)
{
$this->tweets_model->save_raw($raw_tweet, $tweet_id);
}
}
class Consume extends OauthPhire {
public function enqueueStatus($status) {
$tweet_object = #json_decode($status);
if (!(isset($tweet_object->id_str))) { return;}
$tweet_id = $tweet_object->id_str;
$raw_tweet = base64_encode(serialize($tweet_object));
echo $tweet_object->text . "\r\n";
// here i need to use top class method to insert data
//$this->tasks->insert_raw_tweet($tweet_object, $tweet_id);
}
}
$get_track = new Get();
$list = $get_track->getall();
$stream = new Consume(OAUTH_TOKEN, OAUTH_SECRET, Phirehose::METHOD_FILTER);
$stream->setTrack($list);
$stream->consume();
Load it just like you load a normal third party library stored in /library/ folder, use this method :
$this->load->library('OauthPhirehose');
Hope this works.

Switching Classes during __construct()

Let's take the following classes for a moment:
class member {
public $id;
public function __construct($id) {
$this->id = $id;
// Check user level
if ($this->check_user_level() == moderator) {
$this = new moderator($this->id);
}
}
private function check_user_level() {
// Return user level from system based on user ID
}
}
class moderator extends member {
public function show_moderator_tools() {
// etc.
}
}
==================
$user = new member($user_id);
The desired behavior is to have $user detect whether the user is authorized to have moderator access, and if so recast the user using the moderator class instead of member.
PHP forbids simply reassigning $this, so what appears to be the best solution would be one of the following:
Run check_user_level($id) as a regular function and using an if statement
$user_level = check_user_level($id);
if ($user_level == "moderator") {
$user = new moderator($id);
} else {
$user = new member($id);
}
Set a flag in the base class that can be used for a check/redefinition after initializing $user
$user = new member($id);
if ($user->flag = TRUE) {
$user = new moderator($id);
}
The latter feels like it's introducing a security flaw, especially since the flag (which could just as easily be $user->user_level, or similar, I guess) would have to be public to be able to check it afterward.
What I would like to do would be to just make one call to new member($id) and have it handle things automatically from there, without the need for if statements after the fact. Is there a way to do this?
You can of do this by introducing another class (lets call it user) and using the __call magic method in php and call_user_func_array for calling the methods.
The logic is something like this -
Create a user class that has no method except check_user_level. It checks proper details and assigns it's $obj to the instance of either member or moderator class.
Here is how the classes would look like (I've changed the functions to print something out)-
class user{
public function __construct($id) {
$this->id = $id;
if ($this->check_user_level() == "moderator") {
$this->obj = new moderator($this->id);
}else{
$this->obj = new member($this->id);
}
}
public function __call($method, $args){
call_user_func_array(array($this->obj,$method), $args);
}
public function __get($prop){
if(isset($this->obj->$prop)){
return $this->obj->$prop;
}
return NULL;
}
private function check_user_level() {
// Return user level from system based on user ID
if($this->id == 1){
return "moderator";
}
return "member";
}
}
class member {
public $id;
public function __construct($id) {
$this->id = $id;
}
public function show_message($arg){
var_dump($this->id.$arg);
}
}
class moderator extends member{
public function show_moderator_tools() {
var_dump($this->id ."My toolset!");
}
}
So, now you can simply call the user class and that will automatically decide if it's a member or a moderator and call the method if it exists.
//Trying out a few examples
//Creating a member user
$mem_obj = new user(213);
$mem_obj->show_message("New message");
//Creating a moderator user
$mod_obj = new user(1);
$mod_obj->show_moderator_tools();
/*
OUTPUTS
-------
string(14) "213New message"
string(12) "1My toolset!"
*/
But you need to be careful with these kind of hacks.
For instance -
//This will fail
//because mem_obj doesn't have show_moderator_tools()
$mem_obj->show_moderator_tools();
EDIT
You can similarly go ahead with redirecting to properties using __get.
I have modified the code above to add this method beneath __call.
//Testing it
var_dump($mem_obj->id);
//This is an illegal property
var_dump($mem_obj->illegelProperty);
/*
OUTPUTS
int(213)
NULL
*/

Codeigniter Query result returning Custom result object with setters

How exactly does CI custome object works ?
As per CI documentation You can also pass a string to result() which represents a class to instantiate for each result object (note: this class must be loaded)
$query = $this->db->query("SELECT * FROM users;");
foreach ($query->result('User') as $row)
{
echo $row->name; // call attributes
echo $row->reverse_name(); // or methods defined on the 'User' class
}
}
This is a very nice feature yet what Ci does is it will return an array of User objects and set attributes from row to it.
i have a problem with it that i want to have more control on what attributes to be publicly accessed and what to be modified before setting/getting.
how can i accomplish this ? can i tell CI to pass all attributes to constructor so that class can populate its own data ?
example class User
class User{
private $data=array();
protected $CI;
//public $id,$name,$dob,$gender,$role,$username,$password,$salt,$picture,$lastactive;
function __construct($data=null)
{
$this->data = $data; // i want to save data to a private var and allow attr. throu getters only
}
function set_password($p){
$this->generateSalt();
$this->data->password = $p.$this->data->salt;
}
}
In a nutshell::
I want to use custom_result_object but i dont want codeigniter to populate class attributes for me, instead i want the class to receive those attrs and populate it him self the way he this its appropriate.
I found your question while looking for a solution for myself.
After digging a bit in the documentation I managed to figure it out:
class user_item {
// you can declare all the attributes you want as private
private $id,$name,$dob,$gender,$role,$username,$password,$salt,$picture,$lastactive;
function __construct(){
// you can use the constructor to format data as needed
$this->username = strtouppper($this->username);
}
public function set_password($p){
$this->generateSalt();
$this->password = $p.$this->salt;
}
public function get_password(){
return $this->password;
}
}
Once set up, you can instantiate this class from $this->db->result()
class User_model extends CI_Model {
public function get_user($id){
return $this->db->get_where('users', array('id' => $id), 1)->result('user_item');
}
}
And call any public method or attribute of the class as needed
class Users extends CI_Controller {
function __construct(){
$this->load->model('user');
}
public function profile($user_id){
var $myUser = $this->user->get_user($user_id);
$myUser->set_password('myPassword');
echo $myUser->get_password();
}
}
I have simplified the code to make it clearer, but you get the idea.
this example controller using result array and object
if ($this->session->userdata('id_jurusan') ==1) {
$where=array('id_jurusan'=>$this->session->userdata('id_jurusan'));
$value = $this->session->userdata('id_jurusan');
$value2 = $this->session->userdata('username');
$data['rule']=$this->guru_mod->get_where($where,'forward_changing')->result();
$data['fuzzy']=$this->guru_mod->get_data_all('fuzzy')->result();
$data['artikel']=$this->guru_mod->get_data_all('artikel')->result();
$data['kondisi']=$this->guru_mod->get_where($where,'kondisi')->result();
$data['artikel2'] = $this->guru_mod->get_data_all2('artikel','id_jurusan',$value);
$data['riwayat_rule'] = $this->guru_mod->get_data_all2('forward_changing','username',$value2);
$data['kondisi_rule'] = $this->guru_mod->get_data_all2('kondisi','id_jurusan',$value);
$this->load->view('guru/daftar_rule',$data);
}

how to make a global variable in yii

I am learning Yii and I wanted to ask a basic question.
I have a controller and there are two actions in that controller which are as follows
class MyappController extends Controller
{
public $count=0;
public function actionInitialCount()
{
$this->count=1;
$this->redirect('secondCount');
}
public function actionSecondCount()
{
echo $this->count;
}
}
Now what i want is that when the InitialCount action has modified the $count variable to 1. the secondCount to echo it as 1 and not 0. But it echos it as 0 only. So how can i achieve this task that if one action modifies a variable then i can get the modified values in the second action
I think, you are thinking about common variable between two life cycle of application. That is only possible with $_SESSION or other persistent variables . I hope, you understand this.
In side the controller function, you have to use the count variable as
$this->count
So, complete code will be :
class MyappController extends Controller {
public $count=0;
public function actionInitialCount()
{
$this->redirect('secondCount');
}
public function actionSecondCount()
{
echo $this->count;
}
}
Think that i have a class
class AController extends MyController{
//can be accessed here(even in the view) using $this->publicvariable
}
And I say that this is in components
class MyController extends CController{
//My public variable is declared here
}
Now i take different examples.
Example 1
It is simple PHP Program example.
class MyappController {
public $count = 0;
function InitialCount() {
$this->count = 1;
}
function SecondCount() {
print $this->count;
}
}
$ob = new MyappController();
$ob->InitialCount();
$ob->SecondCount();
Example 2
Above same program but in Yii.
class MyappController extends Controller
{
public $count=0;
function __construct() {
$this->count = 7 + 8 ;
}
public function actionIndex()
{
echo $this->count ;
}
public function actionInitialCount()
{
echo $this->count=1;
}
public function actionSecondCount()
{
echo $this->count ;
}
}
Example 3
We can change value by accessing it out side the class.
class MyTest
{
protected $a;
public function __construct($a)
{
$this->a = $a;
}
public function head()
{
echo $this->a;
}
public function footer()
{
echo $this->a;
}
}
$a = 7;
$obj = new MyTest($a);
echo $obj->head();
Actually when you modified your variable value, then you need to declare it, as i have declared in my 1st example, then you can get your changed value.
Secondly like in ecommerce applications, when we purchase different items then it will display modified values each, so it can be accessed through session varialbes, that store information on the server.
If you need your modified value in Yii and display it on the view, so you read about Yii Sessions then you can accomplish your requirement.
In my example of Yii, if you redirect it to the view then it will generate error because i have made Constructor.
Hope it will help you for your understanding.
Thanks.
Can you not just make count a session using Yii::app()->session['count']? What happens now is that the class is being loaded when you call actionInitialCount and again actionSecondCount so the $count will be set back to 0.

Categories