SitePoint Sponsor

User Tag List

Page 3 of 3 FirstFirst 123
Results 51 to 75 of 75
  1. #51
    "Of" != "Have" bronze trophy Jeff Lange's Avatar
    Join Date
    Jan 2003
    Location
    Calgary, Canada
    Posts
    2,063
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    If you have a template designer that you can't trust with the full power of PHP, FIRE THEM RIGHT NOW.
    Sometimes, that is simply not an option.

    If you are writing an application for the use of the general internet population (ie: Forum package, CMS, Portal), the "designer" can be anyone. They're purchasing this product from you, it's up to you to make it user friendly. Easy templating is the answer.
    Who walks the stairs without a care
    It shoots so high in the sky.
    Bounce up and down just like a clown.
    Everyone knows its Slinky.

  2. #52
    SitePoint Addict
    Join Date
    Aug 2003
    Location
    Toronto
    Posts
    300
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    2. Restricting the toolset for template designers. If you have a template designer that you can't trust with the full power of PHP, FIRE THEM RIGHT NOW.
    Never worked on a project that used content submitted by untrusted sources? Why suggest that everyone needs to know PHP and how to defensively program in it just because someone on the programming team happens to use PHP?

    This is a silly argument.

    Besides, syntax is nearly EVERYTHING .

  3. #53
    SitePoint Guru
    Join Date
    May 2003
    Location
    virginia
    Posts
    988
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, I've read these php template threads a hundred times ateast! But we all love 'em right?

    I coded this up tonight... It lets you use short tags and one special bonus. If you use the short tag to print ( <?= ), the output is escaped by htmlentities(xxx, ENT_QUOTES).

    <?= $data ?> becomes: <?php echo htmlentities($data, ENT_QUOTES) ?>
    <? //blah// ?> becomes: <?php //blah// ?>

    The templates get compiled only if the template source file has been updated:

    PHP Code:
    class ShortTagTemplate {
        
        var $file;
        var $data;
        var $_c_file;

        function ShortTagTemplate($file, $data=array()){
            $this->file = $file;
            $this->data = $data;
            $this->_c_file = dirname($this->file) . '/../compiled/' . basename($this->file);
        }
        
        function set($name, $value){
            $this->data[$name] = $value;
        }
        
        function get($name, $value){
            if(isset($this->data[$name])){
                return $this->data[$name];
            }
        }
        
        function toString(){
            $this->_compile();
            extract($this->data, EXTR_REFS);
            ob_start();
            require $this->_c_file;
            return ob_get_clean();
        }
        
        function _compile(){
            if ( file_exists($this->_c_file) ) {
                if( filemtime($this->_c_file) >= filemtime($this->file) ){
                    return;
                }
            }
            
            // get contents of template file
            $contents = file_get_contents($this->file);
            
            // replace all "<?= xxx" with "<?php echo htmlentities(xxx)"
            
    $find = '/\<\?\= ?(.*?)?;? ?\?\>/mis';
            
    $replace = "<?php echo htmlentities(\$1ENT_QUOTES); ?>";
            $contents = preg_replace($find, $replace, $contents);
            
            // replace "<?" with "<?php"
            
    $find = '/\<\?\ (.*)? \?>/';
            
    $replace = "<?php \$1 ?>";
            $contents = preg_replace($find, $replace, $contents);
            
            // write new code to "compiled" template... should do file modified check here
            $f = fopen($this->_c_file, 'w');
            fwrite($f, $contents);
            fclose($f);
        }
        
    }

    $tpl =& new ShortTagTemplate(dirname(__FILE__) . '/templates/source/index.php');
    $tpl->set('title', 'Welcome');
    $tpl->set('body', '<em>This</em> is the body!');
    echo $tpl->toString();

  4. #54
    SitePoint Addict
    Join Date
    May 2005
    Posts
    255
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    Except that seems ignore output escaping, so possibly vulnerable to XSS attacks. If was going to use PHP, you have to <h1>{htmlspecialchars($this->Name)}</h1> etc which then is not very nice templating, hence why I posted the stream based solution earlier, which can magically add output escaping and still retain the simpler syntax.
    Yes, that was a canned example to illustrate a point. In practice, I'd apply filters at the template level (in __get) to take care of this., because I wouldn't expect my template designers to go through the tediousness of having to escape all the output themselves.

    Quote Originally Posted by Jeff Lange
    Sometimes, that is simply not an option.

    If you are writing an application for the use of the general internet population (ie: Forum package, CMS, Portal), the "designer" can be anyone. They're purchasing this product from you, it's up to you to make it user friendly. Easy templating is the answer.
    Except that restricting them doesn't make it more "user friendly", it just makes it more restrictive. They have to learn some weird language that you created and then modify things anyway. PHP is no weirder than most, so you're just adding extra complexity to the system for no real gain. Aside from that, anybody who actually does the template editing is most likely going to actually have at least some idea of what they're doing, anyway. I can say with 100% certainty that your "easy templating" is neither easy nor user friendly, no matter what syntax you're using, and the only person that's ever going to be editing your templates is going to be a technical person in the first place.

    Quote Originally Posted by jayboots
    Never worked on a project that used content submitted by untrusted sources? Why suggest that everyone needs to know PHP and how to defensively program in it just because someone on the programming team happens to use PHP?

    This is a silly argument.

    Besides, syntax is nearly EVERYTHING .
    For these types of systems, users shouldn't be controlling the templates in the first place. Users should be entering content (either with a plain text, wysiwyg, or html input field) and saving it, and your application should handle figuring out how to put that into a template. One possible exception here is plugins or formatting code converters (i.e. bbcode). If you're letting "untrusted sources" submit your PAGE TEMPLATES, then you're far too trusting.

    Templates should be 95% html and 5% php (if that). If you're putting more logic than that into your templates, then you're not really doing a clean enough separation anyway. If someone understands basic html, the odds are pretty good that they'll also understand what

    <?php if($x > 10): ?>
    <p>Hi bob</p>
    <?php endif; ?>

    does, and changing it to something silly like:

    <if condition="$x > 10">
    <p>Hi bob</p>
    </if>

    isn't really going to help.

    If your template writers don't even know HTML, then they shouldn't be your template writers in the first place. Nobody needs to "know" PHP, they need to understand really simple logic constructs. If you're doing anything more than that in your templates, once again, you're doing too much.

    Beyond that, most of the templating methods don't really work well from a performance standpoint. PHP templates can be cached with APC (and the output cached even further, if applicable), but processing other templates means nastiness. You could always do a template->php compiler ala smarty, but the end result of that tends to be a whole lot of changing PHP's states (entering and exiting php mode via <? and ?>), which is slow. Yes, I know, you probably don't think performance matters, but when it takes over 200ms to process these "simple" templates, you're creating a bad end-user experience.

  5. #55
    "Of" != "Have" bronze trophy Jeff Lange's Avatar
    Join Date
    Jan 2003
    Location
    Calgary, Canada
    Posts
    2,063
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I've used my templating system in a commercial application before, and yes, it was user friendly, and yes, it worked well, and no, I had NO CONTROL over who bought the product. At one point it was bought by a group of middle-aged mothers who wanted to discuss doing stuff on the cheap.

    All of my templates are parsed into native PHP, never exiting PHP mode, and are parsed once when they are edited, and never again.

    Code:
    <if $userid>Welcome $username</if>
    Is much easier for a middle-aged housewife, than this:

    PHP Code:
    <?php if ($userid): ?>
       Welcome <?php echo $username?>
       <?php endif; ?>
    You have you're opinion, and that's fine, but using my templating system sold our product better than before we used it, and it made us money. That's the bottom line when running a business. The entire application could be installed, run, setup, changed, etc, without seeing a line of PHP code. It was user-friendly.
    Who walks the stairs without a care
    It shoots so high in the sky.
    Bounce up and down just like a clown.
    Everyone knows its Slinky.

  6. #56
    SitePoint Guru thr's Avatar
    Join Date
    Jun 2003
    Location
    Sweden
    Posts
    664
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    PHP Code:
    <?php if($userid) echo $username?>
    Is also valid php, or:
    PHP Code:
    <?=($userid)?$username:'';?>

  7. #57
    "Of" != "Have" bronze trophy Jeff Lange's Avatar
    Join Date
    Jan 2003
    Location
    Calgary, Canada
    Posts
    2,063
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by thr
    PHP Code:
    <?php if($userid) echo $username?>
    Is also valid php, or:
    PHP Code:
    <?=($userid)?$username:'';?>
    And are either of those easier to understand for a layman? Maybe.

    I was just giving an example. Ternary operators certainly aren't easier.
    Who walks the stairs without a care
    It shoots so high in the sky.
    Bounce up and down just like a clown.
    Everyone knows its Slinky.

  8. #58
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    PHP Code:
        // ...
        
    function _compile(){
            if ( 
    file_exists($this->_c_file) ) {
                if( 
    filemtime($this->_c_file) >= filemtime($this->file) ){
                    return;
                }
            }
            
            
    // get contents of template file
            
    $contents file_get_contents($this->file);
            
            
    // ... do stuff here ..
            // write new code to "compiled" template... should do file modified check here
            
    $f fopen($this->_c_file'w');
            
    fwrite($f$contents);
            
    fclose($f);
        } 
    Hi,

    I know this is not really on topic, but this part code is not safe. Actually its pretty dangerous. There are multiple unsafe critical sections.

    First. What if one thread opens file for writing and then context switches and another thread starts to read (file_get_contents) ? You will get empty/corrupted template.

    Second. If you open a file for writing you must lock it. Try this on your sandbox.

    PHP Code:
    // actual script
    // $fp = fopen('text', 'w');
    // fwrite($fp, $string);
    // fclose($fp);


    // critical section hazard simulation
    // postfix 1 - thread 1
    // postfix 2 - thread 2

    $fp1 fopen('test.txt''w');
    // context switch
    $fp2 fopen('test.txt''w');
    fwrite($fp2'some stuff');
    fclose($fp2);
    // context switch
    fwrite($fp1'stuff');
    fclose($fp1); 
    So what do you think will be in resulting test.txt after execution? Wow - "stuffstuff".

    The problem is that you must always acquire a lock before accessing a shared resource. In this case a file. In PHP this is really tricky because you can't actully acquire lock before opening file. An atomic open&lock would solve this, but AFAIK PHP does not have this.

    I have been trying to solve this problem by writing a thread safe cache.
    http://johno.jsmf.net/knowhow/SafeCache/

    PS. I think there is only a little bug that if you write empty string to cache, it will return null on get() method calls. Working on it.
    Annotations support for PHP5
    TC/OPT™ Group Leader

  9. #59
    SitePoint Zealot DerelictMan's Avatar
    Join Date
    Oct 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    The problem is that you must always acquire a lock before accessing a shared resource. In this case a file. In PHP this is really tricky because you can't actully acquire lock before opening file. An atomic open&lock would solve this, but AFAIK PHP does not have this.
    This is fairly simple to work around by attempting to open and acquire a lock on a separate lock file. Then once the lock on the separate file is obtained, open the actual file in 'w' or 'w+' mode. I do this in both my PHP and Perl scripts.

    Are you aware of a language that natively supports an atomic open+lock?

    Quote Originally Posted by johno
    I have been trying to solve this problem by writing a thread safe cache.
    http://johno.jsmf.net/knowhow/SafeCache/
    As far as I can tell your class still has this problem. In the save() method you are opening the file in "w" mode which truncates it, before acquiring your lock. (This also makes the call to ftruncate() redundant.) Maybe you meant to open it in append mode ('a')? Or am I missing something...

  10. #60
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DerelictMan
    Are you aware of a language that natively supports an atomic open+lock?
    file_get_contents() & file_put_contents() support LOCK_EX flag. fopen has x & x+ for exclusive file creation.

  11. #61
    SitePoint Zealot DerelictMan's Avatar
    Join Date
    Oct 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    file_get_contents() & file_put_contents() support LOCK_EX flag.
    Hmmmm. I see that file_put_contents() supports the flag. It's not mentioned on the file_get_contents() so perhaps the latter always requests a shared lock without requiring the user to specify it.

    I wonder, tho, if this is really an atomic open+lock. I'm sure it's safe if everyone is using file_*_contents(), but what happens if one process uses file_put_contents(), and the other uses standard fopen? In that case there may be a mechanism that file_*_contents() uses that is bypassed. Don't have time to look at the source right now, but I am curious...

    Quote Originally Posted by Ren
    fopen has x & x+ for exclusive file creation.
    Which doesn't help you if the file you are dealing with already exists. The x flags treat that as a failure. There may be some cases where you can't afford to delete the file between writes...

  12. #62
    Put your best practices away. The New Guy's Avatar
    Join Date
    Sep 2002
    Location
    Canada
    Posts
    2,087
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    I have a question for all of you. How do you handle urls? Do you just pass a basic path variable and then hardcode parameters? Or something else? Really interest in the responses.
    "A nerd who gets contacts
    and a trendy hair cut is still a nerd"

    - Stephen Colbert on Apple Users

  13. #63
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DerelictMan
    This is fairly simple to work around by attempting to open and acquire a lock on a separate lock file. Then once the lock on the separate file is obtained, open the actual file in 'w' or 'w+' mode. I do this in both my PHP and Perl scripts.

    Are you aware of a language that natively supports an atomic open+lock?
    Another file as lock? That's a nice solution (I think this is the 'x' flag in fopen). But you have to create another lock file for each file. But a pretty and simple trick. Nice.

    Quote Originally Posted by DerelictMan
    As far as I can tell your class still has this problem. In the save() method you are opening the file in "w" mode which truncates it, before acquiring your lock. (This also makes the call to ftruncate() redundant.) Maybe you meant to open it in append mode ('a')? Or am I missing something...
    Yes it truncates it, but is that a problem? If the file is empty get method returns null.

    ftruncate() is not redundant, its crutial. Try this.
    PHP Code:
    $fp1 fopen('test.txt''w');
    // context switch
    $fp2 fopen('test.txt''w');
    // acquire exclusive lock - thread 2
    fwrite($fp2'some stuff');
    // release lock
    fclose($fp2);
    // context switch
    // acquire exclusive lock - thread 1
    fwrite($fp1'stuff');
    // release lock
    fclose($fp1); 
    After that test.txt will contain "stuffstuff" string. That's without truncate.
    Annotations support for PHP5
    TC/OPT™ Group Leader

  14. #64
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DerelictMan
    Hmmmm. I see that file_put_contents() supports the flag. It's not mentioned on the file_get_contents() so perhaps the latter always requests a shared lock without requiring the user to specify it.
    Ah remembered incorrectly, thought LOCK_EX was available for both.

    Anyways, shouldn't you write to a tmpfile()/tmpnam() and use atomic rename() and chmod so it isnt writable?

  15. #65
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by mwmitchell
    <?= $data ?> becomes: <?php echo htmlentities($data, ENT_QUOTES) ?>
    <? //blah// ?> becomes: <?php //blah// ?>
    I quite like that. It's like C's preprocessor, which makes you make really obscure macro-stuff.
    Perhaps if we add a short-tag for <?php echo $this->XXX; ?> (Where XXX is the content of the tag). Something like <?#url("foo/bar")?>

  16. #66
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DerelictMan
    I wonder, tho, if this is really an atomic open+lock. I'm sure it's safe if everyone is using file_*_contents(), but what happens if one process uses file_put_contents(), and the other uses standard fopen? In that case there may be a mechanism that file_*_contents() uses that is bypassed. Don't have time to look at the source right now, but I am curious...
    Seems file_put_contents() with locking from look at the source is equivalent to

    $handle = fopen($name, $mode);
    if (flock($handle, LOCK_EX))
    return FALSE;
    ...

  17. #67
    SitePoint Wizard silver trophy kyberfabrikken's Avatar
    Join Date
    Jun 2004
    Location
    Copenhagen, Denmark
    Posts
    6,157
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by The New Guy
    I have a question for all of you. How do you handle urls? Do you just pass a basic path variable and then hardcode parameters? Or something else? Really interest in the responses.
    I have a class URLBuilder, which builds url's to the applications resources.
    PHP Code:
    class Template extends DataSpace
    {
        var 
    $file;
        var 
    $url NULL;

        function 
    Template($file) {
            
    parent::DataSpace();
            
    $this->file $file;
        }

        function 
    render() {
            
    extract($this->_dataEXTR_REFS);
            
    ob_start();
            include(
    $this->file);
            return 
    ob_get_clean();
        }

        function 
    url($href ""$args = Array(), $stateful NULL) {
            if (
    $this->url) {
                return 
    $this->url->url($href$args$stateful);
            }
            
    $urlbuilder =& Components::GetService('FrontController/URLBuilder');
            return 
    $urlbuilder->url($href$args$stateful);
        }

    PHP Code:
    class FrontController_URLBuilder
    {
        var 
    $base "/";
        var 
    $current "";

        var 
    $_page = Array();

        function 
    FrontController_URLBuilder($base "/"$current "") {
            
    $this->base $base;
            
    $this->current $current;
        }

        
    /**
          * @param    $stateful    TRUE to include state, FALSE to not include state or NULL to autodetermin (within same page)
          */
        
    function url($href ""$args = Array(), $stateful NULL) {
            if (
    is_null($href)) {
                
    $href $this->current;
            }
            
    $href ltrim($href"/");
            
    $href rtrim($href"?");
            if (!
    preg_match("~^http://~"$href)) {
                
    $href $this->base.$href;
            }
            if (
    preg_match("/(.*)\\?(.*)/"$href$matches)) {
                
    $href $matches[1];
                
    parse_str($matches[2], $parsed);
                
    $args array_merge($parsed$args);
            }
            
    // precedence of arguments is : arg -> urlargs -> pagestate
            
    if ((is_null($stateful) && rtrim($href"/") == rtrim($this->current"/")) || $stateful === TRUE) {
                
    // page state
                
    $args array_merge($this->_page$args);
            }
            
    $params = Array();
            foreach (
    $args as $key => $value) {
                if (!
    is_null($value)) {
                    
    $params[] = rawurlencode($key)."=".rawurlencode($value);
                }
            }
            if (
    count($params) > 0) {
                if (
    strpos($href"?") === FALSE) {
                    return 
    $href."?".implode("&"$params);
                } else {
                    return 
    $href."&".implode("&"$params);
                }
            }
            return 
    $href;
        }

        function 
    get($property) {
            return isset(
    $this->_page[$property]) ? $this->_page[$property] : NULL;
        }

        function 
    set($property$value) {
            
    $this->_page[$property] = $value;
        }


  18. #68
    SitePoint Guru 33degrees's Avatar
    Join Date
    May 2005
    Posts
    707
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Security/trust issues aside, another problem with using php directly in your templates is that it simply isn't very readable. My latest project has required some pretty complex templates, and even with helper functions, I sometimes have trouble figuring out exactly what's going on.

  19. #69
    SitePoint Zealot DerelictMan's Avatar
    Join Date
    Oct 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    Another file as lock? That's a nice solution (I think this is the 'x' flag in fopen).
    The 'x' flag fails if the file exists, which is often not desirable...
    Quote Originally Posted by johno
    Yes it truncates it, but is that a problem? If the file is empty get method returns null.
    The problem with it is that it truncates the file before it has determined if it is safe to do so. By the time your save() method acquires the lock it has already wiped the file's contents.

    Consider this:

    Code:
    Process A                     Process B
    ------------                 ------------
     $c->get()                    ...
       fopen()                    ...
       acquireLock()              ...
       getFileContents()          ...
         inside fread() loop      $c->save($data)
         ...                        fopen() <--just truncated file even though Process A has it locked
         ...                        acquireLock()
         end fread() loop             inside flock() loop <--waiting for lock
       fclose() <--lock released      ...
     ...                              end flock() loop <--lock acquired
     ...                            write data...
    In the above scenario Process A read corrupt data. It had already read a portion of the file but before it could finish Process B truncated it, even though Process A had a lock. I could come up with a similar scenario where one process truncates the file while another one is writing to it, meaning that the file would only contain the last portion of the contents the first process was writing. Bottom line is that truncating the file before you have a lock is dangerous, if you don't want processes to read corrupt or incomplete data. The separate lock file approach avoids this because you can open the separate lock file safely even if you don't have a lock because you aren't writing to it... it's just a gatekeeper to the actual file.

    Quote Originally Posted by johno
    ftruncate() is not redundant, its crutial. Try this.
    PHP Code:
    $fp1 fopen('test.txt''w');
    // context switch
    $fp2 fopen('test.txt''w');
    // acquire exclusive lock - thread 2
    fwrite($fp2'some stuff');
    // release lock
    fclose($fp2);
    // context switch
    // acquire exclusive lock - thread 1
    fwrite($fp1'stuff');
    // release lock
    fclose($fp1); 
    After that test.txt will contain "stuffstuff" string. That's without truncate.
    Ok, I see, but you still have the problem of fopen() truncating before the lock is acquired. If you solve that problem an ensure that fopen(..., 'w'); is only called by one process at a time then the call to ftruncate() will not be needed...

  20. #70
    SitePoint Zealot DerelictMan's Avatar
    Join Date
    Oct 2005
    Posts
    123
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Ren
    Anyways, shouldn't you write to a tmpfile()/tmpnam() and use atomic rename() and chmod so it isnt writable?
    Yes, I had forgotten about that. Although as far as I know this only works on unix (not Windows), and it only works if the temp file is on the same volume as the destination file, which may be difficult to ensure in all cases...
    Quote Originally Posted by Ren
    Seems file_put_contents() with locking from look at the source is equivalent to

    $handle = fopen($name, $mode);
    if (flock($handle, LOCK_EX))
    return FALSE;
    ...
    It's opaque to me, but then again I'm not a C guy, and I don't have a firm grasp on how streams are implemented, which it seems file_put_contents() uses. It still seems to me that if you're not appending and file_put_contents() eventually calls the underlying fopen() in 'w' mode you may have a problem. But surely the PHP devs considered this so it's probably safe. As for me, I'll stick with my separate lock file approach as it seems to work in all cases and keeps me from worrying.

  21. #71
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by DerelictMan
    Yes, I had forgotten about that. Although as far as I know this only works on unix (not Windows), and it only works if the temp file is on the same volume as the destination file, which may be difficult to ensure in all cases...
    tmpnam() does take a dir to try and ensure they're both on the same volume, thou it does fallback to system standard if that fails.

    It's opaque to me, but then again I'm not a C guy, and I don't have a firm grasp on how streams are implemented, which it seems file_put_contents() uses. It still seems to me that if you're not appending and file_put_contents() eventually calls the underlying fopen() in 'w' mode you may have a problem. But surely the PHP devs considered this so it's probably safe. As for me, I'll stick with my separate lock file approach as it seems to work in all cases and keeps me from worrying.
    Yes, file_put_contents() opens in 'w' or 'a' mode, depending on flags ( FILE_APPEND).

  22. #72
    Put your best practices away. The New Guy's Avatar
    Join Date
    Sep 2002
    Location
    Canada
    Posts
    2,087
    Mentioned
    1 Post(s)
    Tagged
    1 Thread(s)
    Thanks kyberfabrikken. Extemely helpful.
    "A nerd who gets contacts
    and a trendy hair cut is still a nerd"

    - Stephen Colbert on Apple Users

  23. #73
    SitePoint Zealot johno's Avatar
    Join Date
    Sep 2003
    Location
    Bratislava, Slovakia
    Posts
    184
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Seems like I and DerelictMan have found a solution for these locking issues.

    The magic combinations are:

    For reading: fopen with 'r' flag, acquire shared lock with flock, read data, release lock, fclose.

    For writing: fopen with 'a' flag, acquire exclusive lock, truncate file, write data, release lock, fclose.

    Implementation has been fixed. http://johno.jsmf.net/knowhow/SafeCache/
    Annotations support for PHP5
    TC/OPT™ Group Leader

  24. #74
    SitePoint Wizard Ren's Avatar
    Join Date
    Aug 2003
    Location
    UK
    Posts
    1,060
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by johno
    Seems like I and DerelictMan have found a solution for these locking issues.

    The magic combinations are:

    For reading: fopen with 'r' flag, acquire shared lock with flock, read data, release lock, fclose.

    For writing: fopen with 'a' flag, acquire exclusive lock, truncate file, write data, release lock, fclose.

    Implementation has been fixed. http://johno.jsmf.net/knowhow/SafeCache/
    Pretty sure the locking should include LOCK_NB (Non blocking). Also flock() has problems with ISAPI.

  25. #75
    SitePoint Addict
    Join Date
    May 2005
    Posts
    255
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Jeff Lange
    I've used my templating system in a commercial application before, and yes, it was user friendly, and yes, it worked well, and no, I had NO CONTROL over who bought the product. At one point it was bought by a group of middle-aged mothers who wanted to discuss doing stuff on the cheap.

    All of my templates are parsed into native PHP, never exiting PHP mode, and are parsed once when they are edited, and never again.

    Code:
    <if $userid>Welcome $username</if>
    Is much easier for a middle-aged housewife, than this:

    PHP Code:
    <?php if ($userid): ?>
       Welcome <?php echo $username?>
       <?php endif; ?>
    You have you're opinion, and that's fine, but using my templating system sold our product better than before we used it, and it made us money. That's the bottom line when running a business. The entire application could be installed, run, setup, changed, etc, without seeing a line of PHP code. It was user-friendly.
    But are the non-technical people actually doing the template editing? At a minimum, you're going to have someone who knows HTML doing that, and for someone who knows HTML neither system is terribly complicated. Your implementation takes away flexibility for those that need it for the sake of so-called "user friendliness", which in practice isn't ever actually going to matter.

    If your users ever *need* to see your templates in any form (PHP or otherwise), then it's a bad system. There's absolutely nothing wrong with users "needing" to see a little PHP inside of a template. As long as you're not putting heavy business logic in there, it's not anything that's ever going to really confuse the average moderately technical person.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •