views:

58

answers:

4

I need to have a variable that only one function can write (let's call that function a) and that only one other function can read (let's call that function b). Is that possible?

+6  A: 

You could use a static variable:

function foo($val=null) {
    static $var = null;
    if (!is_null($var)) $var = $val;
    return $val;
}

Here $var is only visible inside the function foo and is maintained throughout multiple calls:

foo(123);
echo foo();  // 123
foo(456);
echo foo();  // 456

Or use a class with a private member and access/modify it with public methods:

class A {
    private $var;
    public function setVar($val) {
        $this->var = $val;
    }
    public function getVar() {
        return $this->var;
    }
}

With this the private member var is only visible to a particular instance of this class:

$obj1 = new A();
$obj1->setVar(123);
$obj2 = new A();
$obj2->setVar(456);
echo $obj1->getVar();  // 123
echo $obj2->getVar();  // 456

If you make the member static, then there is just one for the class instead of for each instance:

class A {
    private static $var;
    public function setVar($val) {
        self::$var = $val;
    }
    public function getVar() {
        return self::$var;
    }
}
$obj1 = new A();
$obj1->setVar(123);
$obj2 = new A();
$obj2->setVar(456);
echo $obj1->getVar();  // 456
echo $obj2->getVar();  // 456
Gumbo
+1 for private class variables
Fanis
I know this probably isn't possible but I would like to make reading the variable possible for one function only. Your `private member` example doesn't restrict $var from being read from another method (other than getVar()).
Emanuil
@Emanuil: If you are afraid of an unwanted inheritance, then you could make the class [final](http://php.net/language.oop5.final).
Gumbo
+1  A: 

You can use a static abstract class.

abstract class Settings
{
    private static var $_settings = array();

    public static function get($key,$default = false)
    {
        return isset(self::$_settings[$key]) ? self::$_settings[$key] : $default;
    }

    public static function set($key,$value)
    {
        self::$_settings[$key] = $value;
    }
}

Example Usage:

Settings::set('SiteName',`SomeResult`);

echo Settings::get('SiteName');
RobertPitt
+1  A: 

Since 5.3.0, you can use anonymous functions as closures. The advantage here, is that you can hold on to b... which is returned by a... and fire it off when you're ready:

<?php
function a()
{
    // Only a() can write to $myVar
    $myVar = 42;
    $b = function() use ($myVar)
    {
        // $b can read $myVar
        // no one else can
        return $myVar;      
    };
    return $b;
}

  // get $b
$test = a();
  // use $b
echo $test();
?>

Another solution before 5.3.0, but here a has to fire b which may not be that practical:

You can simply create an internal variable and pass it as an argument. You can do this inside a class, or just inside simple functions:

function a()
{
    // ...
    // Write the variable that
    // only this function can write to
    $thisVar = 1;
    b($thisVar);
    //...
}

function b($myVar)
{
    // ...
    // Do stuff w $myVar, a copy of $thisVar
    // Changing $myVar has no effect on $thisVar
    //
}
Peter Ajtai
Yes, that's probably closest to what I'm looking for. The problem is it doesn't satisfy the condition that only `b` can read the var as `a` here can also do that.
Emanuil
@Emanuil - What do you mean `a` can read the var? How can it write something it can't read?
Peter Ajtai
@Peter Ajtai: Well, I have no idea. As I stated earlier, I'm pretty sure it's impossible. Thought it's worth asking, though.
Emanuil
@Emanuil - Well, can you describe why you need to do this?
Peter Ajtai
@Peter Ajtai: I'm building a simple MVC framework. I want the controllers and only the controllers to be able to write data somewhere and the views and only the views to be able to read it.
Emanuil
@Emanuil - You should probably add that to the question. I'm not familiar with MVC, so I don't know if that's a good idea, or if there are other ways to achieve that. ---- Also, I added closures to my answer, since I think that's a more practical solution to your original question.
Peter Ajtai
@Peter Ajtai: I probably should have added more context to the question. Thanks for your help! I appreciate it.
Emanuil
+1  A: 

Do you mean friend functions? Because I'd love to be able to do that. So far I haven't found an easy way though (although you could try using Reflection, but that seems like way to much effort).

For me, it usually hasn't been an issue of maintaining data integrity / encapsulation, but of keeping the list of public methods (which is kinda like a class's API) free of clutter. A perfect framework should be easy to use, have obvious function names etc etc etc. Methods intended for use by a single other method really mess things up. The "solution" I've taken to is prefixing those function names by one or two underscores and writing "intended for internal use only" or something to that extent in the comments.

Michael Clerx