how to use $this inside a function that is inside a method? - php

I have a function that is inside a class method.
In the method I can refer to $this but I cannot in the function. It will return this error:
Fatal error: Using $this when not in
object context in
/var/www/john/app/views/users/view.ctp
on line 78
Here is an example of what I mean:
class View
{
var $property = 5;
function container()
{
echo $this->property;
function inner()
{
echo "<br/>Hello<br/>";
echo $this->property;
}
inner();
}
}
$v = new View();
$v->container();
You can test it here pastie
Is there a work around to make this work?
I know I can pass $this in as a parameter, but is there any other way? Using global $this gives an error also.
If your curious why I need this, its because my method is a view in an MVC model (or so it seems - I am using Cake), and in the view I need to use a function, and in the function I need to refer to $this.

do not make a function within another function, try this:
class View {
var $property = 5;
function container() {
echo $this->property;
$this->inner();
}
function inner() {
echo "<br/>Hello<br/>";
echo $this->property;
}
}

why not pass it with a parameter?
function inner($instance)
{
echo "<br/>Hello<br/>";
echo $instance->property;
}
inner($this);

I cannot yet comment, so I'm posting this answer instead.
This question seems CakePHP related to me, and I think you're overdoing the View. As an example consider reading Post Views from the CakePHP Blog Example
To sum up: if you are inside a CakePHP View, then you just output HTML with embedded PHP. The View has access to variables that you have set in the Controller action (i.e. UserProfiles::index). What I'd suggest is using something like the following:
<h2>UserProfile for <?php echo $user->name; ?></h2>
<?php if( $user->isAdmin() ): ?>
<p>You're an admin</p>
<?php else: ?>
<p>You're just a user</p>
<?php endif; ?>
Also I'd suggest looking at Elements, you can include them conditionally if required conditions are met ;).

When PHP comes across a function definition, it defines the function into the global scope. So although you declare your function within a method, the scope of the function is actually global. Therefore the only way to access $this from within inner() would be to pass it as a parameter. And even then it would behave slightly differently than $this because you wouldn't be within the scope of the object.

Related

Nested function property accessibility

I want to access testProperty in the below example, but this is inside a nested function (extending twig, it has to be nested), but it of course says
"Using $this when not in object context".
I simply can't open another 'public function' inside an existing one. Does anyone know how to fix this?
I want a global variable in the entire class, without using global.
class test
{
private testProperty;
public function testFunction() {
function abc() {
var_dump($this->testProperty)
}
}
}
I didn't fix the problem exactly as I wanted it stated, but I did fix it in my document. I placed my function outside and made it public and just changed al my abc() to $this->abc() really dumb oversight of mine
If my guess of what you're trying to achieve is correct, you may want to do something like this:
class test
{
private $testProperty = "whatever";
public function testFunction() {
$abc = function() {
var_dump($this->testProperty);
};
$abc();
}
}
$x = new test;
$x->testFunction();
Since $abc is now an anonymous function, it has $this variable available when used inside a class method.
The code above will output:
string(8) "whatever"

How to Pass a function to a class in php

I have a class that generates data based on a few things. I would like to format that data from the outside. So I am trying to pass a function into the class so that it would format that data. I have looked at many examples, but it seems this is unique.
Can anybody give an idea of how to do this? The following code gives an error.
<?php
class someClass {
var $outsideFunc; // placeholder for function to be defined from outside
var $somevar='Me'; // generated text
function echoarg($abc){
$outsideFunc=$this->outsideFunc; // bring the outside function in
call_user_func($outsideFunc,$abc); // execute outside function on text
echo $abc;
}
}
function outsidefunc($param){ // define custom function
$param='I am '.$param;
}
$someClass=new someClass();
$someClass -> outsideFunc = 'outsideFunc'; // send custom function into Class
$someClass -> echoarg($someClass->somevar);
$someClass -> outsidefunc = 'outsidefunc';
In PHP, function names are not case sensitive, yet object property names are. You need $someClass->outsideFunc, not $someClass->outsidefunc.
Note that good OOP design practice calls for the use of getter and setter methods rather than just accessing properties directly from outside code. Also note that PHP 5.3 introduced support for anonymous functions.
Yeah. You are right. Now there is no error. But it does not work either.
By default, PHP does not pass arguments by reference; outsidefunc() does not actually do anything useful. If you want it to set $param in the caller to something else, and do not want to just return the new value, you could change the function signature to look like this:
function outsidefunc(&$param) {
You would also need to change the way you call the function, as call_user_func() does not allow you to pass arguments by reference. Either of these ways should work:
$outsideFunc($abc);
call_user_func_array($outsideFunc, array(&$abc));
Why not pass your function as an argument?
<?php
class someClass {
public $somevar="Me";
public function echoarg($abc,$cb=null) {
if( $cb) $cb($abc);
echo $abc;
}
}
$someClass = new someClass();
$someClass->echoarg($someClass->somevar,function(&$a) {$a = "I am ".$a;});
i am not sure what exactly you are looking for, but what i get is, you want to pass object in a function which can be acheive by
Type Hinting in PHP.
class MyClass {
public $var = 'Hello World';
}
function myFunction(MyClass $foo) {
echo $foo->var;
}
$myclass = new MyClass;
myFunction($myclass);
OP, perhaps closures are what you're looking for?
It doesn't do EXACTLY what you're looking for (actually add function to class), but can be added to a class variable and executed like any normal anonymous function.
$myClass->addFunc(function($arg) { return 'test: ' . $arg });
$myClass->execFunc(0);
class myClass {
protected $funcs;
public function addFunc(closure $func) {
$this->funcs[] = $func;
}
public function execFunc($index) { $this->funcs[$index](); } // obviously, do some checking here first.
}

How to access "$this" from a function

I use an homemade MVC system, in which Views access the model by being within the context of a method, and therefore able to access $this.
Example of a view, included dynamically :
...
<div>
Hello <?= $this->user->name ?>
</div>
...
Now, I have some code that I would like to factorize into functions, with some extra parameters.
For example :
function colored_hello($color) {
?>
<div style="background-color:<?= $color ?>">
Hello <?= $this->user->name ?>
</div>
<?
}
The problem is that I do not have access to $this, since the function is not a method.
But I do not want to spoil my model or controller with presentation stuff.
Hance, I would like to be able to call this function dynamically, as a method.
Like aspect oriented programming :
# In the top view
magic_method_caller("colored_hello", $this, "blue")
Is it possible ?
Or do you see a better way of doing it ?
Take a look at Closure::bindTo
You'll have to define/call your functions slightly differently, but you will be able to access $this from inside your object.
class test {
private $property = 'hello!';
}
$obj = new test;
$closure = function() {
print $this->property;
};
$closure = $closure->bindTo($obj, 'test');
$closure();
Pass $this as a property, but in all seriousness: you shouldn't really have functions in your view files.
it is a bit a hack but you can use debug_backtrace() to get the callers object. But I think you can only public values:
function colored_hello($color) {
$tmp=debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
$last=array_pop($tmp);
$caller = $last['object'];
print_r($tmp);
print_r($last);
print_r($caller);
?>
<div style="background-color:<?= $color ?>">
Hello <?= $caller->user->name ?>
</div>
<?
}
(code is not testet but it gives you a hint :-) )
You could alternatively pass it into the function:
function coloured_hello($object, $color) {
//Code
$object->user->name;
}

Calling member function from other member function in PHP?

I'm a little confused about the situation shown in this code...
class DirEnt
{
public function PopulateDirectory($path)
{
/*... code ...*/
while ($file = readdir($folder))
{
is_dir($file) ? $dtype = DType::Folder : $dtype = Dtype::File;
$this->push_back(new SomeClass($file, $dtype));
}
/*... code ...*/
}
//Element inserter.
public function push_back($element)
{
//Insert the element.
}
}
Why do I need to use either $this->push_back(new SomeClass($file, $dtype)) or self::push_back(new SomeClass($file, $dtype)) to call the member function push_back? I can't seem to access it just by doing push_back(new SomeClass($file, $dtype)) like I would have expected. I read When to use self over $this? but it didn't answer why I need one of them at all (or if I do at all, maybe I messed something else up).
Why is this specification required when the members are both non-static and in the same class? Shouldn't all member functions be visible and known from other member functions in the same class?
PS: It works fine with $this-> and self:: but says the functions unknown when neither is present on the push_back call.
$this->push_back will call the method as part of the CURRENT object.
self::push_back calls the method as a static, which means you can't use $this within push_back.
push_back() by itself will attempt to call a push-back function from the global scope, not the push_back in your object. It is not an "object call", it's just a plain-jane function call, just as calling printf or is_readable() within an object calls the usual core PHP functions.
I cant seem to access it just by doing push_back(new SomeClass($file, $dtype)) like I would have expected.
This way you call push_back() as a function. There is no way around $this (for object methods) or self::/static:: (for class methods), because it would result into ambiguity
Just remember: PHP is not Java ;)
You can access like this
public static function abc($process_id){
return 1;
}
public static function xyz(){
$myflag=self::abc();
return $myflag;
}
output : 1

how can i include php file in php class

i have php with an array i.e
$var = array(
"var" => "var value",
"var2" => "var value1"
);
and have another file with a class i.e
class class1{
function fnc1(){
echo $var['var2'];
//rest of function here
}
}
now how can i get $var['var'] in class file in function fnc1()
You can pass it as an argument, or use the global keyword to put it in the current scope.
However, using global is discouraged, try passing it as an argument.
Pass it as an argument?
class class1{
function fnc1($var) {
echo $var['var2'];
}
}
And in your other file call this class method with your array as an argument.
From: http://php.net/manual/en/function.include.php
When a file is included, the code it contains inherits the variable scope of the line on which the include occurs. Any variables available at that line in the calling file will be available within the called file, from that point forward. However, all functions and classes defined in the included file have the global scope.
So you could do
class class1
{
function fnc1()
{
include 'thefile.php'
echo $var['var2'];
//rest of function here
}
}
but like others pointed out before, you dont want to do that, because it introduces a dependency on the filesystem in your class. If your method requires those variables to work, then inject them as method arguments or pass them into the constructor and make them a property (if you need them more often). This is called Dependency Injection and it will make your code much more maintainable in the long run, e.g. do
class class1
{
private $data;
public function __construct(array $var)
{
$this->data = $var;
}
function fnc1()
{
echo $this->data['var2'];
//rest of function here
}
}
and then do
$obj = new class1($var);
echo $obj->fnc1();
or require the data to be passed into the method on invocation
class class1
{
function fnc1(array $var)
{
echo $var['var2'];
//rest of function here
}
}
and then
$obj = new class1;
$obj->fnc1($var);
You might use global $var in your included file, but it's really a bad practice, as another script, before your included file, might redefine the value/type of $var.
Example :
class class1{
function fnc1(){
global $var;
echo $var['var2'];
//rest of function here
}
}
A better solution, is to pass your $var as a parameter to your fnc1(), even to your class1::__construct()
#Vindia: I'd prefer the argumant-style too, but would recommend either using type hint or a simple check to avoid warnings when accessing *non_array*['var2']:
// acccepts array only. Errors be handled outside
function fnc1(Array $var) {
echo $var['var2'];
}
// accepts any type:
function fnc1(Array $var) {
if (is_array($var)) {
echo $var['var2'];
}
}
class class1{
function fnc1(){
include 'otherFile.php';
echo $var['var2'];
//rest of function here
}
}

Categories