php-general Digest 31 Mar 2006 16:48:25 -0000 Issue 4045

Topics (messages 232982 through 232990):

setting the same value to multiple variables
        232982 by: charles stuart
        232983 by: Jasper Bryant-Greene
        232984 by: charles stuart

Re: Overloading Limitation- Can Someone Confirm?
        232985 by: Jochem Maas
        232989 by: Jim Lucas

Re: HTTP status code
        232986 by: gustav.varupiraten.se

Failing to write to a file when a class is being implicitly destroyed
        232987 by: John Wells
        232988 by: Jochem Maas

Going loopy with arrays.....
        232990 by: Jay Blanchard

Administrivia:

To subscribe to the digest, e-mail:
        [EMAIL PROTECTED]

To unsubscribe from the digest, e-mail:
        [EMAIL PROTECTED]

To post to the list, e-mail:
        php-general@lists.php.net


----------------------------------------------------------------------
--- Begin Message ---
Hi,

I'm sure this is quite basic. Nonetheless I'm new to PHP so I haven't figured it out.

I'd like to set each variable to the same value (without having to set that value individually for each variable).

Thanks for the help.


best,

Charles



if ( 1 == 1 )
{
$goodToGo = 0; $errorArray[] = "You must declare some goals on Activity 1.";


// this block of code does not set each variable to "class=\"errorHere \"";

        $readingGoalsEnjoymentLabelClass &&     
        $readingGoalsInformationLabelClass &&
        $readingGoalsAlphabeticLabelClass &&    
        $readingGoalsPrintLabelClass && 
        $readingGoalsPhonologicalLabelClass &&
        $readingGoalsPhoneticLabelClass &&      
        $readingGoalsComprehensionLabelClass &&
        $readingGoalsVocabularyLabelClass &&    
        $readingGoalsInstructionsLabelClass &&
        $readingGoalsCriticalLabelClass &&      
        $readingGoalsCommunicateLabelClass = "class=\"errorHere\"";
}

--- End Message ---
--- Begin Message ---
charles stuart wrote:
if ( 1 == 1 )

^^ what is the point of this?

{
$goodToGo = 0; $errorArray[] = "You must declare some goals on Activity 1.";

// this block of code does not set each variable to "class=\"errorHere\"";

$readingGoalsEnjoymentLabelClass && $readingGoalsInformationLabelClass && $readingGoalsAlphabeticLabelClass && $readingGoalsPrintLabelClass && $readingGoalsPhonologicalLabelClass && $readingGoalsPhoneticLabelClass && $readingGoalsComprehensionLabelClass && $readingGoalsVocabularyLabelClass && $readingGoalsInstructionsLabelClass && $readingGoalsCriticalLabelClass && $readingGoalsCommunicateLabelClass = "class=\"errorHere\"";
}

While this seems like excessively ugly code (have you considered an array? what is the point of all those variables if they all hold the same value?), replace all of those '&&' with '=' and you will be fine. PHP evaluates right-to-left and the result of an assignment is the value that was assigned, so that will work.

--
Jasper Bryant-Greene
General Manager
Album Limited

http://www.album.co.nz/     0800 4 ALBUM
[EMAIL PROTECTED]          021 708 334

--- End Message ---
--- Begin Message ---
On Mar 30, 2006, at 11:01 PM, Jasper Bryant-Greene wrote:

charles stuart wrote:
if ( 1 == 1 )

^^ what is the point of this?


Just cutting out the long IF statement so everyone didn't have to look past it.

{
$goodToGo = 0; $errorArray[] = "You must declare some goals on Activity 1."; // this block of code does not set each variable to "class= \"errorHere\""; $readingGoalsEnjoymentLabelClass && $readingGoalsInformationLabelClass && $readingGoalsAlphabeticLabelClass && $readingGoalsPrintLabelClass && $readingGoalsPhonologicalLabelClass && $readingGoalsPhoneticLabelClass && $readingGoalsComprehensionLabelClass && $readingGoalsVocabularyLabelClass && $readingGoalsInstructionsLabelClass && $readingGoalsCriticalLabelClass && $readingGoalsCommunicateLabelClass = "class=\"errorHere\"";
}

While this seems like excessively ugly code (have you considered an array? what is the point of all those variables if they all hold the same value?), replace all of those '&&' with '=' and you will be fine. PHP evaluates right-to-left and the result of an assignment is the value that was assigned, so that will work.

Ah, I see. Thanks.

I place the variable in the <label> tag for each of the corresponding inputs (checkboxes in this case). If none are checked (at least one is required) I set an error message at the top of the page and then set a background color on each <label> via the now present class="errorHere".

I'm sure there's a better way to do this, but I'm not the best with PHP. I'll look into using an array.

Thanks again for your help. You've shortened my code at least a little bit.


best,

Charles

--- End Message ---
--- Begin Message ---
Jasper Bryant-Greene wrote:
Jochem Maas wrote:

Jasper Bryant-Greene wrote:

Jochem Maas wrote:

I think its a misunderstanding on the one side and a limitation on the other,
you can't use overloading directly on items of an overloaded array e.g:

    echo $tc->arr['a']

this is triggers a call to __get() with the $key parameter set to something like
(I'm guessing) "arr['a']"



No, I'm pretty sure (too lazy and tired right now to test...) that if


you guess wrong :-)  .. I couldn't resist testing it:

php -r '
class T { private $var = array();
function __set($k, $v) { $this->var[$k] = $v; }
function __get($k)     { var_dump($k); }
}
$t = new T;
$t->arr = array();
$t->arr["a"] = 1;
echo "OUTPUT: \n"; var_dump($t->arr); var_dump($t->arr["a"]); var_dump($t);
'


That's weird, because I did get around to testing it before I saw your mail, and in my test it works as *I* expect (PHP 5.1.2)...

a couple of things: I tested on 5.0.4  yesterday (should have mentioned that)
- just tried on 5.1.1 and the behaviour there _seems_ to agree
with your premise ... but not completely; the outcome is expected but the
code doesn't do what I believe it should be doing with regard to
guarding against arbitrary crap into an object via __set() - I assume people
use __set() to protect variables, in the same way as 'normal' setters
are often used. I modified you test code a little - notice how __set()
is only called once (the second 'set' is actually a 'get'!):

<?php

class T {

    private $array = array();

    public function __get( $key ) {
        echo "Getting $key\n";
        return $this->array[$key];
    }

    public function __set( $key, $value ) {
        echo "Setting $key\n";
        $this->array[$key] = $value;
    }

}

$t = new T;

$t->insideArray = array();
$t->insideArray["test"] = "testing!";

var_dump( $t );

?>

OUTPUT:

Setting insideArray
Getting insideArray
object(T)#1 (1) {
  ["array:private"]=>
  array(1) {
    ["insideArray"]=>
    array(1) {
      ["test"]=>
      string(8) "testing!"
    }
  }


I personally feel that the fact that $t->array['insideArray']['test'] is
being set (why does __set() seem to return a reference) is unwanted ...
it circumvents any variable checking logic I might have in __set()

how do like them apples? ;-)

--- End Message ---
--- Begin Message ---
Jasper Bryant-Greene wrote:
Jochem Maas wrote:
Jasper Bryant-Greene wrote:
Jochem Maas wrote:

I think its a misunderstanding on the one side and a limitation on the other, you can't use overloading directly on items of an overloaded array e.g:

    echo $tc->arr['a']

this is triggers a call to __get() with the $key parameter set to something like
(I'm guessing) "arr['a']"


No, I'm pretty sure (too lazy and tired right now to test...) that if

you guess wrong :-)  .. I couldn't resist testing it:

php -r '
class T { private $var = array();
function __set($k, $v) { $this->var[$k] = $v; }
function __get($k)     { var_dump($k); }
}
$t = new T;
$t->arr = array();
$t->arr["a"] = 1;
echo "OUTPUT: \n"; var_dump($t->arr); var_dump($t->arr["a"]); var_dump($t);
'


That's weird, because I did get around to testing it before I saw your mail, and in my test it works as *I* expect (PHP 5.1.2)...

My comments earlier were based on the fact that it would not be good to limit what can be put in an object through __get and __set effectively to scalar variables, and I would expect the engine developers to realise that. I think they have (unless I've done something stupid in my test code...):

Code:

<?php

class T {

    private $array = array();

    public function __get( $key ) {
        return $this->array[$key];
    }

    public function __set( $key, $value ) {
        $this->array[$key] = $value;
    }

}

$t = new T;

$t->insideArray = array();
$t->insideArray['test'] = 'testing!';

var_dump( $t );

?>

Output:

object(T)#1 (1) {
  ["array:private"]=>
  array(1) {
    ["insideArray"]=>
    array(1) {
      ["test"]=>
      string(8) "testing!"
    }
  }
}

Dont know if you guys see the MAJOR difference between your code, so I will point it out.

Jasper did this

function __get($k)     {
   var_dump($k);
}

Jochem did this

public function __get( $key ) {
  return $this->array[$key];
}

First off, the required public before the function call was not included, secondly, Jasper is var_dumping the key of the array, not the array it self.

Hope this helps

And yes, it should work the way Jochem was expecting. At least that is what the manual says, and my testing says. But you have to make sure you include all the needed parts to make it work correctly.

Thanks Jim

--- End Message ---
--- Begin Message ---
> No,
> I'm creating remote service and it's returning codes according to passed
> parameters. I only wanted to test it using browsers...
>
> I do not care about the output actually, but the status code
>
> B.
>
It seems to me, that this is more html-related. Maybe the tags in the
html-document screws it up regarding to the use of html. IE is more
insensitive regarding correct typing of html-tags.

>>header('HTTP/1.1 404 Not Found');
>>header("Status: 404 Not Found");

Why do you have ' on the first line and " on the second?

/Gustav Wiberg

> Jasper Bryant-Greene wrote:
>> The default Apache error handler is not called when PHP sends a 404
>> header. The code that does Apache error handling happens *before* PHP
>> gets in the loop, and checks to see if the script being referenced
>> exists, which it indeed does, whether it sends a 404 header or not.
>>
>> Tested on Apache 2.2 with PHP 5.1.
>>
>> If you really want to get the default Apache error handler to appear
>> then either readfile() it or redirect to it.
>>
>> Jasper
>>
>> Anthony Ettinger wrote:
>>
>>> well, you typically would redirect 404 to something like
>>> foo.com/404.html
>>>
>>> Otherwise, it's whatever your server (apache/IIS) has as the default
>>> 404 handler...
>>>
>>> Default is something like this:
>>>
>>>               Not Found
>>>
>>>               The requested URL /asdf was not found on this server.
>>>               Apache Server at foo.org Port 80
>>>
>>>
>>> On 3/30/06, Jasper Bryant-Greene <[EMAIL PROTECTED]> wrote:
>>>
>>>> In other words, if you want Firefox/Opera/etc to display something,
>>>> you
>>>> have to output something. Strange, that. :P
>>>>
>>>> Jasper
>>>>
>>>> Anthony Ettinger wrote:
>>>>
>>>>> Then it's working....FireFox, et. al. show you the server 404, IE on
>>>>> the otherhand has it's own 404 error page (for those newbies who
>>>>> don't
>>>>> know what a 404 is). You can disable it under IE options.
>>>>>
>>>>> On 3/30/06, Bronislav Klucka <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>>> Yes, I do...
>>>>>> B.
>>>>>>
>>>>>> Anthony Ettinger wrote:
>>>>>>
>>>>>>> Are you seeing the IE-specific 404 page? The one that looks like
>>>>>>> this:
>>>>>>>
>>>>>>> http://redvip.homelinux.net/varios/404-ie.jpg
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 3/30/06, Bronislav Klucka <[EMAIL PROTECTED]> wrote:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>> I'm using following construction to send http status code
>>>>>>>> --------------
>>>>>>>> header('HTTP/1.1 404 Not Found');
>>>>>>>> header("Status: 404 Not Found");
>>>>>>>> exit;
>>>>>>>> --------------
>>>>>>>>
>>>>>>>> MSIE displays "Page not found", but FireFox and Opera don't
>>>>>>>> display
>>>>>>>> anything. Just blank page with no text...
>>>>>>>>
>>>>>>>> full headers sent by this script (and server itself) are:
>>>>>>>>
>>>>>>>> --------------
>>>>>>>> Date: Thu, 30 Mar 2006 18:02:49 GMT
>>>>>>>> Server: Apache/2.0.55 (Debian) PHP/4.4.0-4 mod_ssl/2.0.55
>>>>>>>> OpenSSL/0.9.8a
>>>>>>>> X-Powered-By: PHP/5.1.2
>>>>>>>> Keep-Alive: timeout=15, max=99
>>>>>>>> Connection: Keep-Alive
>>>>>>>> Transfer-Encoding: chunked
>>>>>>>> Content-Type: text/html
>>>>>>>>
>>>>>>>> 404 Not Found
>>>>>>>> --------------
>>>>>>>>
>>>>>>>> can anyone tell me, why those two browsers are not affected?
>>>>>>>>
>>>>>>>> Brona
>>>>>>>>
>>>>>>>> --
>>>>>>>> PHP General Mailing List (http://www.php.net/)
>>>>>>>> To unsubscribe, visit: http://www.php.net/unsub.php
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Anthony Ettinger
>>>>>>> Signature: http://chovy.dyndns.org/hcard.html
>>>>>>>
>>>>>> --
>>>>>> PHP General Mailing List (http://www.php.net/)
>>>>>> To unsubscribe, visit: http://www.php.net/unsub.php
>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>> --
>>>>> Anthony Ettinger
>>>>> Signature: http://chovy.dyndns.org/hcard.html
>>>>>
>>>> --
>>>> Jasper Bryant-Greene
>>>> General Manager
>>>> Album Limited
>>>>
>>>> http://www.album.co.nz/     0800 4 ALBUM
>>>> [EMAIL PROTECTED]          021 708 334
>>>>
>>>>
>>>
>>>
>>> --
>>> Anthony Ettinger
>>> Signature: http://chovy.dyndns.org/hcard.html
>>>
>>
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>

--- End Message ---
--- Begin Message ---
I hope I can explain my problem/questions clearly. Thanks in advance:

------------
Scenario:
I'm working on a Log class that my app will use to write
debug/error/etc messages to a file.  I've created it so that as the
application logs messages, these messages are queued within a property
of the Log class, and only written to the file when the Log object is
being destroyed.

I wanted to place all of the file writing to within __destruct() to
avoid holding a connection to the log file throughout the life of the
app's state.

------------
Problem:
Everything works fine, UNLESS I move the fopen('log-file-name') call
to within the __destruct() method.  If I open a handle to the log file
within the __construct() method, or any other class method, it works
fine.  But I receive a permissions error if it's called within
__destruct().

Error reads: "Warning: fopen(20060331.txt) [function.fopen]: failed to
open stream: Permission denied in ......."

------------
Caveat:
I have found that if I explicitly destroy an instance of Log with
unset(), then fopen() will work even when it is within the
__destruct() method.  However I don't like that solution...and
besides, I'm planning on creating an instance of the Log class from
within the __construct() of my Controller class, and trying to
explicitly destroy Log with an implicit __destruct() of my Controller
doesn't work either. :P

------------
Question(s):
1. Could anyone explain a bit more as to why fopen() won't work within
an implicit call to __destruct()?  What permissions has my app lost at
this point?
2.  Am I at least correct in my intention to limit the duration that
the handle to the log file is open?
3. Is there workaround to this little conundrum that anyone can think of?

------------
Code:
Here's a simplified version of the code (it's complete, feel free to
copy-and-paste-and-play).  I've commented the fopen code block in
question.

[code]
        // Create an instance of Log
        $log = new Log();
        // Attempt to log a message
        Log::debug("Here is a debug message.");

        class Log
        {
                protected static $handle;
                protected static $location;
                protected static $message;

                public function __construct()
                {
                        self::$location = date("Ymd").".txt";
/* Begin fopen() */
/* When placed here, it works */
                        if (!self::$handle = fopen(self::$location,"a"))
                        {
                                echo "Error. Please check permissions.";
                                die;
                        }
/* End fopen() */
                }
                
                public static function debug($message)
                {
                        $timestamp = date("Y-m-d H:i:s T");
                        self::$message .= $timestamp."\tdebug\t".$message."\n";
                }
                
                public function __destruct()
                {
                        if(self::$message)
                        {
/* Begin fopen() */
/* If it's here, it won't work!
                                if (!self::$handle = fopen(self::$location,"a"))
                                {
                                        echo "There was an error attempting to 
open the log file. Please
check permissions.";
                                        die;
                                }
/* End fopen() */
                                if (fwrite(self::$handle, self::$message) === 
FALSE)
                                {
                                        echo "Cannot write to file 
({$this->location})";
                                        exit;
                                }
                                @fclose(self::$handle);
                        }
                }
        }

[/code]

-John W

--- End Message ---
--- Begin Message ---
basically when php shutsdown at some stage stuff like file manipulation,
db access will have been torn down - the implicit object destruction (and
therefore the call to __destruct() happens to late in the shutdown process
to be of any use ... there is a big chicken and egg problem there (search the
archives of the php-internal mailing list should reveal lots of discussion
surround this topic)

further comments below ...

John Wells wrote:
I hope I can explain my problem/questions clearly. Thanks in advance:

------------
Scenario:
I'm working on a Log class that my app will use to write
debug/error/etc messages to a file.  I've created it so that as the
application logs messages, these messages are queued within a property
of the Log class, and only written to the file when the Log object is
being destroyed.

I wanted to place all of the file writing to within __destruct() to
avoid holding a connection to the log file throughout the life of the
app's state.

------------
Problem:
Everything works fine, UNLESS I move the fopen('log-file-name') call
to within the __destruct() method.  If I open a handle to the log file
within the __construct() method, or any other class method, it works
fine.  But I receive a permissions error if it's called within
__destruct().

Error reads: "Warning: fopen(20060331.txt) [function.fopen]: failed to
open stream: Permission denied in ......."

------------
Caveat:
I have found that if I explicitly destroy an instance of Log with
unset(), then fopen() will work even when it is within the
__destruct() method.  However I don't like that solution...and
besides, I'm planning on creating an instance of the Log class from
within the __construct() of my Controller class, and trying to
explicitly destroy Log with an implicit __destruct() of my Controller
doesn't work either. :P

that's probably due to references still existing (according to the engine)
to you Log object.


------------
Question(s):
1. Could anyone explain a bit more as to why fopen() won't work within
an implicit call to __destruct()?  What permissions has my app lost at
this point?

it's seems rather odd that the error would return a permission problem.
I don't get that at all.

2.  Am I at least correct in my intention to limit the duration that
the handle to the log file is open?

it's a good idea yes - any system will have some kind of max as to the
number of open files that are allowed/capable.

3. Is there workaround to this little conundrum that anyone can think of?

explicit destruction. may try working with register_shutdown_function()
- the ctor of your log object could register a 'flsuh' method to be run at
shutdown (which may well be at an early enough stage that opening/writing
files is still possible)

personally I avoid __destruct() - it gives me headaches and never seems
capable of doing what I think it should be able to!


------------
Code:
Here's a simplified version of the code (it's complete, feel free to
copy-and-paste-and-play).  I've commented the fopen code block in
question.

[code]
        // Create an instance of Log
        $log = new Log();
        // Attempt to log a message
        Log::debug("Here is a debug message.");

        class Log
        {
                protected static $handle;
                protected static $location;
                protected static $message;

                public function __construct()
                {
                        self::$location = date("Ymd").".txt";
/* Begin fopen() */
/* When placed here, it works */
                        if (!self::$handle = fopen(self::$location,"a"))
                        {
                                echo "Error. Please check permissions.";
                                die;
                        }
/* End fopen() */
                }
                
                public static function debug($message)
                {
                        $timestamp = date("Y-m-d H:i:s T");
                        self::$message .= $timestamp."\tdebug\t".$message."\n";
                }
                
                public function __destruct()
                {
                        if(self::$message)
                        {
/* Begin fopen() */
/* If it's here, it won't work!
                                if (!self::$handle = fopen(self::$location,"a"))
                                {
                                        echo "There was an error attempting to 
open the log file. Please
check permissions.";
                                        die;
                                }
/* End fopen() */
                                if (fwrite(self::$handle, self::$message) === 
FALSE)
                                {
                                        echo "Cannot write to file 
({$this->location})";
                                        exit;

the 'die' and 'exit' in the code directly above is probably a really bad idea!
and given that the code is currently living in a dtor rather unnecessary?


                                }
                                @fclose(self::$handle);
                        }
                }
        }

[/code]

-John W


--- End Message ---
--- Begin Message ---
Howdy all!

Here is hoping that Friday is just another day in paradise for everyone.

I have an array, a multi-dimensional array. I need to either

a. loop through it and recognize when I have com upon a new sub-array so
that I can do 'new' output
2. OR get each of the sub-arrays out as individual arrays.

Here is a sample;

Array
(
    [H7] => Array
        (
            [0] => Array
                (
                    [lon] => -99.2588
                    [lat] => 29.1918
                )

            [1] => Array
                (
                    [lon] => -99.2205
                    [lat] => 29.1487
                )

            [2] => Array
                (
                    [lon] => -99.23
                    [lat] => 29.1575
                )

            [3] => Array
                (
                    [lon] => -99.242
                    [lat] => 29.1545
                )
        )

    [H6] => Array
        (
            [0] => Array
                (
                    [lon] => -99.0876
                    [lat] => 29.216
                )

            [1] => Array
                (
                    [lon] => -99.0618
                    [lat] => 29.179
                )
And so on ....

I am sure that it has something to do with my lack of sleep and the
looming of deadlines and this being something that I thought would be
trivial. Can someone drop-kick me in the right direction please? The sub
arrays need to be the points in each of the arrays with a H identifier
(H7, H6 etc.)

Thanks!

--- End Message ---

Reply via email to