Dim private $var from function?

So I know that Zend does this in some way, but I’m not sure how. I also found this a hard topic to google on.


class my_class {
  private $var1; //I'd like to do this based on my_func input

  public function my_func($arr) {
    foreach ($arr as $var) {
       $this->$var = null;
    }
  }
}

This might not make sense looking at it, but what I want to do is be able to introduce a new private variable to be used within the class. While this MAY work as is, I’m not able to define public/private. Any ideas?

What exactly are you trying to do? Make a member of the class read only?

If so look into the magic __get and __set functions here.

I don’t know what you’re trying to achieve, but exposing private members to the outside world will cause problems. Especially in such a generic way. Imagine one of your private variables is a dependency, for the sake of argument let’s say private $db; is a database connection. In your code, if ‘db’ is contained in the array sent to my_func, it will be wiped out. Whoops! Clearly this is a very fundamental encapsulation violation.

No. I want to be able to create a new private variable from outside the class. See $var1? I want to make $var2 usable as a private var from within a function of that class.

Obviously I would check to make sure the variable doesnt exist already.

In Zend framework, from the controller I can do $this->view->whateverIWant = ‘something’ and $this->whateverIWant is available for use in the view. I want to do the same.

I’m struggling with trying to understand when this would be useful or an appropriate use case. How would your other methods make use of a dynamically created private variable? How would they know it exists?

Apart from that, I would think an easier approach is to just store an associative array privately that you can append new keys/values to.

Zend framework has a use for it… The entire MVC process is built on it. I was entertaining the idea of throwing custom types of “operations” into my benchmark class.

Really, you’re after this:


class Foo {
	private $vars = array();
	
	public function __set($key, $value) {
		$this->vars[$key] = $value;
	}
	
	public function __get($key) {
		return $this->vars[$key];
	}
}


However, this is (As you have discovered!) difficult for people to debug and doesn’t provide a clear API. And the less said about “MVC” where the controller assigns variables to the view, the better.

Well that would depend completely on how loosely I am going to use it.

Am I wrong?

Controllers shouldn’t be in the business of assigning variables to views. Controllers find the view and model appropriate to the user’s request, then the view asks the model questions as needed to compose itself. Fail to do it the correct way and you lose the decoupling of components MVC is supposed to provide and create a mountain of busy box code for yourself. For example, consider a page that displays customers. The model has their name, addresses, and so on. If you want to change a view to display the full address rather than just the city you should be able to do so just by changing the view. Do it the way you describe and you’ll have to change the view and the controller, doubling your work and creating inefficient, error prone code.

Contrary to a lot of misinformed models of MVC for PHP out there, there isn’t anything wrong with allowing views to ask models for data. And before anyone trots out the “restricted access” argument, yes I understand that the controller is to enforce access. It does this by providing a view with a model that has the access restriction already applied. One user may get a view and the public model of the data, while an admin would get a the same view with the admin model of the data. The flexibility to do this is the reason for the separation scheme of MVC in the first place.

I strong recommend against it. My recommendation is to extend from ArrayObject. Properties of the object you need to protect or make private can be granted that status, and the public data of the object will be browsable via array access. You can even stop worrying about collisions. A real world example…


<?php
class Template extends ArrayObject {
  private $template = '';
  public __construct($template) {
    $this->template = $template;
  }
}

Lots of code not related to the example excluded here. In the example our Template class gets assigned a template when it is constructed. You might even use __get and __set to allow restricted access to that value, like throwing an error if someone attempts to change the template to a non-existent file. Meanwhile, the values bound to my template aren’t affected by the property. $this[‘template’] has an entirely different value (if it is even set) than $this->template. And if you don’t write any getter or setter $object[‘template’] will be read/writable from the outside world, but $object->template will throw an error.

A major advantage of this approach over the old Zend approach (newer objects in Zend 2 use the method I’m describing themselves) is that it separates your data from the settings that affect that data, depending on the object that is carrying them.

EDIT: You do lose one thing in this exchange. Iteration over the object properties is no longer possible - instead you’ll iterate over the underlying array object.


<?php
class A extends ArrayObject {
  public $foo = 1;
  protected $bar = 2;
  private $mar = 3;

  public function loopOver() {
    foreach ($this as $key => $value) {
      echo $key .' '. $value;
    }
  }
}

$a = new A();

foreach ($a as $key => $value) {
  echo $key.' '.$value; // nothing happens, storage array empty.
}

$a->loopOver(); // Again nothing happens.. storage empty

$a['fruit'] = 'apple';
$a['nut'] = 'walnut';
$a['veggie'] = 'tomato';

foreach ($a as $key => $value) {
  echo $key.' '.$value; // fruit apple nut walnut veggie tomato
}

$a->loopOver(); // fruit apple nut walnut veggie tomato

All things considered though, that’s hardly a significant loss and can be used to your advantage if you plan for it.

Is “whateverIWant” private? It doesn’t look that way, because you’re setting it from outside the view class (from the controller). And if it isn’t private, then it may not be true that Zend does exactly what you’re looking for. And what you’re looking for may not be possible.

The closest you can get is probably Tom’s suggestion in post #8, where setting a property actually keys it into an array, and the array is declared private.

The privacy of a variable can be bypassed by __set and __get, allowing the coder to control exactly how the values are set. Whenever an attempt is made to access a class member from a prohibited context those magic functions get invoked. They are also invoked if an attempt is made to access a member that doesn’t exist at all.

And if it isn’t private, then it may not be true that Zend does exactly what you’re looking for. And what you’re looking for may not be possible.
Oh it’s possible. Now ask if its advisable, but I answered that eariler in the thread.

The closest you can get is probably Tom’s suggestion in post #8, where setting a property actually keys it into an array, and the array is declared private.

Which, at that point, is a poor man’s ArrayObject. It’s just easier to extend from that class as I outlined above.

As Michael Morris said, all you do by using the Controller as a mediator is create extra work for yourself. The View should query the model and display the data. I won’t go too off topic but I’ve written about this extensively (see the 2nd link in my signature) because it’s such a widely copied mistake. I’ve yet to find a “MVC” framework that’s actually MVC. They’re all PAC. This misunderstanding was described in detail by Larry Garfield back in 2006: http://www.garfieldtech.com/blog/mvc-vs-pac but if anything, since then it’s become worse because there’s more frameworks incorrectly labelling themselves as “MVC” and all the established frameworks actually use PAC.

[quote=“K_Wolfe,post:9,topic:26369”]

Am I wrong?[/QUOTE]

The definitions of MVC were written with desktop applications in mind, and it doesn’t translate perfectly to stateless, server-side applications. MVC controllers are supposed to handle user input – which could be mouse clicks, key presses, touches, gestures, device orientation, etc. – and translate that input into commands for the view and the model. But on the web, there’s only one input: the HTTP request. MVC views are supposed to be able to react to user input, as well as to changes in the model. But on the web, there won’t be any new user input for the view to react to, nor will there be any changes to the model that would require the view to update itself.

Because of these differences, MVC was a bit bastαrdized in its adaptation to the web. Views in web applications are little more than templates. And the templates don’t access the model directly. Instead they are fed data by the controller, which acts as a mediator between the model and the view. It turns out there’s another design pattern that more accurately reflects the way web applications work, called Presentation–abstraction–control.

But even though what we’ve been using all this time isn’t MVC in its purest sense, I personally think that the architecture that web applications have settled on is a good one. I think it’s a good thing that the views/templates don’t access the model directly. It lets them stay small in scope, ignorant of – and independent of – the larger application.

Both websockets and AJAX calls make this less true than it once was. Increasingly view code is written with javascript, with the server side code feeding the js the data it requests (and authenticating the right for the client to access that data).

But even though what we’ve been using all this time isn’t MVC in its purest sense, I personally think that the architecture that web applications have settled on is a good one. I think it’s a good thing that the views/templates don’t access the model directly. It lets them stay small in scope, ignorant of – and independent of – the larger application.

I disagree - all that approach accomplishes is to shunt to or (worse) duplicate the logic of value binding in the controller, where it doesn’t belong. The problem becomes even more magnified when clientside javascript viewcode is brought into the mix which may need nothing more from the server side control and model than a “yes” or “no”, yet by putting the data binding in the controller the controller - for this purpose at least - becomes unusable.

Whichever architecture is better, it’s not good for anyone to have two architectures with the same name. Advantages/Disadvantages aside, don’t call it MVC if it’s not MVC, it makes discussions on the topic very difficult because nobody is quite sure what’s being discussed.That said, the reason we call “web MVC” “MVC” in the first place is because the creators of Ruby on Rails (and subsequently CakePHP which cloned it) were trying to implement MVC on the web without fully understanding how MVC was designed to work. On the other hand, the original architecture was developed by incredibly clever academics who thought very carefully about what they were trying to achieve “web mvc” was stumbled upon by people attempting to port MVC to the web.

But even though what we’ve been using all this time isn’t MVC in its purest sense, I personally think that the architecture that web applications have settled on is a good one. I think it’s a good thing that the views/templates don’t access the model directly. It lets them stay small in scope, ignorant of – and independent of – the larger application.

It’s not, you end up with far too much code in the controllers. I won’t go into detail because it’s off topic (see the links in my signature if you want to see my thoughts on the matter) but you end up with display logic (What the view should be displaying) and model logic (the application state) inside the controller. The whole point of using MVC (or a similar architecture) is Separation of Concerns. Using the *******ised implementation you sacrifice most of that and most of your code isn’t reusable. For instance, using a different controller with an existing view without duplicating a very large chunk of code or having some hacky inheritance workaround.

In my experience, the loss of reusability, or the un-separation of concerns, that you or Michael claim, simply doesn’t happen. But the “Ya-huh, Nuh-uh” arguments probably won’t get us very far. :stuck_out_tongue: One day we’ll have to set up a mock project to see how it all actually plays out in code. I may put together a mock Symfony project so everyone can see how and why it doesn’t happen.

You can always set the ArrayObject::STD_PROP_LIST flag and use get_object_vars() if you did want to iterate over the object’s properties: it’s not “no longer possible”.