Showing object private properties - php

This is homework. I have created 2 classes, Objecte and Ordinador. It is mandatory that Ordinador properties are private, and $preu in Objecte too.
<?php
class Objecte
{
var $model;
private $preu;
public function __construct($model,$preu)
{
$this->model=$model;
$this->preu=$preu;
}
}
?>
This is Ordinador:
<?php
include('classe_objecte.php');
class Ordinador extends Objecte
{
private $disc_dur;
private $ram;
public function Ordinador($model,$preu,$disc_dur,$ram)
{
parent::__construct($model,$preu);
$this->disc_dur=$disc_dur;
$this->ram=$ram;
}
}
?>
So I have stored some objects I've created. They're stored in a SESSION array. So now I must show the values, but as they're private in the classes, I get this errors:
Notice: Undefined property: Ordinador::$preu
Fatal error: Cannot access private property Ordinador::$disc_dur
Any suggestions how to access to it?.

You have to create a public function that calls to the private var
public function getPreu(){
return $this->preu;
}

instead of:
parent::__construct($model,$preu);
try:
$this->__construct($model,$preu);

In this case I'm storing the objects like this:
$index=$_SESSION['numOrdinadorsO'];
$_SESSION['objetos_ordinador'][$index]=inserirOrdinadorO();
And funtion inserirOrdinadorO looks like this:
function inserirOrdinadorO()
{
$_SESSION['ordinadorsO']=array('model_ordinadors'=>$_POST['model_ordinadors'],'preu_ordinadors'=>$_POST['preu_ordinadors'],'tamany'=>$_POST['tamany'],'ram'=>$_POST['ram']);
$model=$_SESSION['ordinadorsO']['model_ordinadors'];
$preu=$_SESSION['ordinadorsO']['preu_ordinadors'];
$disc_dur=$_SESSION['ordinadorsO']['tamany'];
$ram=$_SESSION['ordinadorsO']['ram'];
$ord_tmp = new Ordinador($model,$preu,$disc_dur,$ram);
$_SESSION['numOrdinadorsO']+=1;
echo "Objecte Ordinador inserit.</br>";
return $ord_tmp;
}
Not sure how to implement the solution Yair gave me:
$obj = new Objecte('modele','preu'); And then echo $obj->getPreu();

Related

can I access private variable in method in same class?

I have this controller
class PageController extends Controller
{
private $myid;
public funciton index(){
}
public function viewbyid($id){
$this->myid = $id;
return view('someview');
}
public function getRecord(){
$id = $this->myid;
echo $id; //it would be null here,if I am going to access this method.
return view('anotherview');
}
}
Yes, you can access private varible, in side class any where, Your using OOPS PHP. So may be problem is you might be accessing getRecord() method with diff object.
For Eg:
$obj=new PageController();
$obj->viewbyid("Test");
$obj->getRecord();//Then it will display the result
If your reinitialize an object or creating new object then that object will reallocate memory, so previous saved values will not be present.
For Eg:
$obj=new PageController();
$obj->viewbyid("Test");
$obj=new PageController();//$obj will allocate memory in diff location so your previous values will be initialized to default.
$obj->getRecord();//Then it will display result as 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);
}

PHP - Closure in class , getting private property

I'm attempting to get a private property from another class using closures, as explained here:
http://ocramius.github.io/blog/accessing-private-php-class-members-without-reflection/
So, I'm trying to get the $wheelCount property.
But I keep getting
Fatal error: Cannot access private property Car::$wheelCount
So my car class is:
class Car
{
private $wheelCount = 4;
public function __construct($wheely)
{
echo $wheely->getWheels($this);
}
}
and then
class getThoseWheels
{
public function getWheels($that)
{
$wheels = Closure::bind($this->getPrivate($that), null, $that);
var_dump($wheels);
}
public function getPrivate($that)
{
return $that->wheelCount;
}
}
which is run:
$wheely = new getThoseWheels();
new Car($wheely);
$wheels = Closure::bind($this->getPrivate($that), null, $that);
The problem is that you're executing $this->getPrivate(), and this method is trying to access a private property. All this happens before Closure::bind is being involved at all. You're supposed to use it like this:
$wheels = Closure::bind(function () { return $this->wheels; }, $that, $that);
Or possibly:
$wheels = Closure::bind([$this, 'getPrivate'], null, $that);
I haven't tested this, but at least this has a much better chance of succeeding than your code.

Attempt to assign property of non-object error

I am getting this error and i can't see what i am doing wrong. I have done the same thing with other objects from other classes which are built in the exact same way and i can't see why i am getting this error now.
The code in which i create the object is this one:
$consulta2 = "SELECT * FROM TiposDireccion WHERE Cliente_CIF='$cif' and Direccion_Direccion='$direccion' and Direccion_CP=$cp ";
echo($consulta2."</br>");
if ($resultado2 = $conexion->query($consulta2)){
while($fila2 = $resultado2->fetch_object()){
$tipodireccion78=$fila2->TipoDireccion_Tipo;
//we see here that the select is returning a correct string with a correct value
echo($tipodireccion78);
//we try to instantiate and it fails =(
$unTipoDireccion=TipoDireccion::constructor1($tipodireccion78);
This is the class TipoDireccion:
<?php
class TipoDireccion{
private $tipo;
private $descripcion;
//Construct auxiliar
function __construct() {
}
//Constructor 1 : completo
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
function ponTipo($tipo) {
$this->tipo = $tipo;
}
function devuelveTipo() {
return $this->tipo;
}
function ponDescripcion($descripcion) {
$this->descripcion = $descripcion;
}
function devuelveDescripcion() {
return $this->descripcion;
}
}
?>
Thank you a lot in advance!
Don't know if this is still relevant to you, but in case anyone else comes on here for an answer. The problem is in this function:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->tipo = $tipo;
return $tipoDireccion;
}
Because in the class definition, you define private $tipo; and then you try and assign $tipoDireccion->tipo to what was passed through the function. However, you aren't trying to access that variable through the scope of the class, you are trying to assign it from the 'public' scope as far as the class is concerned.
The fix for this has two options, the first one would be to change private $tipo; to public $tipo;. But that isn't a good solution as you have an assignment function for it.
Instead, use your functions that you made, which would make the function look like:
function constructor1($tipo) {
$tipoDireccion = new TipoDireccion();
$tipoDireccion->ponTipo($tipo);
return $tipoDireccion;
}
That's how you need to access it from the public scope, which you are doing after you initiate a new one.
function constructor1($tipo) {}
should be
static function constructor1($tipo) {}

Mock private method in a test function by PHPUnit

Writing unit tests for code which is already written is fun sometimes.
I am writing a test case for the following code (an example):
<?php
class mockPrivate {
public static function one($a){
$var = static::_two($a);
return $var;
}
private static function _two($a){
return $a+1;
}
}
?>
The test class is like this:
<?php
require_once 'mockPvt.php';
class mockPrivate_test extends PHPUnit_Framework_TestCase {
public $classMock;
protected function setUp(){
$this->classMock = $this->getMock('mockPrivate', array('_two'));
}
public function test_one(){
$a = 1;
$retVal = 2;
$classmock = $this->classMock;
$classmock::staticExpects($this->once())
->method('_two')
->with($a)
->will($this->returnValue($retVal));
$value = $classmock::one($a);
$this->assertEquals($value, $retVal);
}
}
?>
After running by $ phpunit mockPrivate_test.php I got this error:
PHP Fatal error: Call to private method Mock_mockPrivate_531a1619::_two() from context 'mockPrivate' in /data/www/dev-sumit/tests/example
s/mockPvt.php on line 6
But if I change the
private static function _two()
to
public static function _two() or
protected static function _two()
it works totally fine. Since this is a legacy code I can't change the private to public/protected. So is there any way I can test the function one or Is this a limitation of phpunit?
Another option is to create a class that extends mockPrivate, allowing accessibility to the object you wish to test. Your engineers should be thinking long and hard about why something is private (because that means the class is not easily extensible). Also remember that you can mock the test class if you need to override what it returns.
class Test_MockPrivate extends MockPrivate
{
/**
* Allow public access to normally protected function
*/
public static function _two($a){
return parent::_two($a);
}
}
// Code to force the return value of a now public function
$mock = $this->getMock('Test_MockPrivate', array('_two'));
$mock->expects($this->any())
->method('_two')
->will($this->returnValue('Some Overridden Value');
You can use reflection for changing visibility of methods. You can find more info in
PHP object, how to reference?
Use mock and reflection... (posted this solution, since this is the top google result)
$oMock = $this->getMock("Your_class", array('methodToOverride'));
$oMock->expects( $this->any() )
->method('methodToOverride')
->will( $this->returnValue( true ) );
$oReflection = new ReflectionClass("Your_Class");
$oMethod = $oReflection->getMethod('privateMethodToInvoke');
$oMethod->setAccessible( true );
$oMethod->invoke( $oMock );

Categories