Jump to content



Photo
- - - - -

Creating a file in PHP?

php files server

  • Please log in to reply
5 replies to this topic

#1   MrPhil

MrPhil
  • Members
  • 6,975 posts
  • Real Name:Phil
  • Gender:Male

Posted 27 April 2016 - 23:33

I have a general question about servers and files. It is possible in PHP to write out a file on the server, say, temp.php created by index.php. If this file has a fixed name, is this file accessible to every user of this site (which I don't want)? That is, is there only one copy at a time, or does every user (potentially hundreds at any given moment) somehow get their own copy?

 

I'm toying with the idea of having a PHP file (both HTML and PHP code) written out by index.php and then run (PHP header Location call). If the name of the file is not somehow unique, I fear I will run into problems with conflicts and race conditions. For example, if User A runs index.php to create temp.php, and a fraction of a second later, User B does the same (with slightly different content), might User A end up running User B's temp.php? Or, User A ends up trying to run an empty temp.php, because User B has just truncated temp.php in preparation for rewriting it. Can these things really happen, or am I overthinking it? I saw this very thing happen with Simple Machines Forum's configuration file when it was rewritten on the fly to record error events (yes, a very stupid design).

 

I suppose there's an alternative in that I can make a really ugly and complex index.php that ends up outputting only HTML (directly to the browser), without an intermediate PHP file. I guess this is sort of what a Content Management System like WordPress, Joomla, or Drupal does, but I really don't want to reinvent such a thing. Do osC's "hooks" work anything like this? This is something that is probably too much to put in a cookie or HTML local storage or in a database. It would be so nice to just write a PHP file and be able to run it (letting the server take care of code execution), if I can be sure that multiple users won't step on each other.

 

PHP gives the ability to write a file, and PHP is normally run on a server (with multiple active users at any one time). Can it really keep everyone's same-named files separate, or was it never intended to? I can't think of how it would do that. I could also try to give each new file a unique name (or unique directory with mkdir), but that would be ugly looking, and there is the danger of cluttering up the server with thousands of no-longer-needed temporary files, which would need to be cleaned out on a regular basis (once run). Someone must have solved this problem before! Suggestions or hints welcome.



#2   Jack_mcs

Jack_mcs
  • Members
  • 28,356 posts
  • Real Name:Jack
  • Gender:Male

Posted 28 April 2016 - 01:01

I'm not sure I understand what you are trying to do. But you can only have one instance of a file with a certain name. That file can't be changed while in use by someone else. So if customer A creates the file and then completes whatever it is he is doing with that file, then customer B can then write to the file or delete it and then create it. But if customer B tries to do that while the file is being used by customer A, the operation will fail. The file should be locked while the writing is going on. The second operation will still fail but should do so without causing a crash.

 

This sort of coding goes against dynamic web sites and shouldn't be done. You should have one file and then have it load whatever it is that needs to be loaded. So lets say customer A creates a file in the tmp directory with a unique name. The common file can be called to load that unique tmp file. At the same time, customer B can create another uniquely named file and the common file can then load it.

 

Without understanding what it is you want to accomplish, I can't offer more detail than that but I hope it helps.



#3   MrPhil

MrPhil
  • Members
  • 6,975 posts
  • Real Name:Phil
  • Gender:Male

Posted 28 April 2016 - 02:39

OK, so you confirm my suspicions that multiple users writing to, say, temp.php will either step on each other, or be blocked (by locking) and be serialized rather than operating in parallel. Neither is good.

 

What I'm thinking about doing is having page "templates" that include HTML which gets plugged into my framework. That would be simple enough to do in index.php, and output directly to the browser. However, they also include blocks of PHP code that provide data for the HTML and/or output HTML. You might think of it as a "CMS Lite". It's not hard to use this template + framework to create a normal .php file, which would be thrown over the wall for the server to run. If given a unique name, and erased after use, this could be done, but I'm trying to avoid awkward-looking file names and doing such cleanup.

 

Instead of creating a PHP file, I'm pondering the use of eval(), on either individual lines or whole blocks of PHP code, but I'd prefer not to mix in the template code with my surrounding framework (index.php) code and variables any more than I have to. There would be two-way data traffic between the two, e.g., set a default <title> in the framework, let PHP code (from the template) modify the <title> string, and the framework actually outputs the HTML <title>. Even if that works, I'm concerned about the framework and template data accidentally stepping on each other. That's why being able to throw the whole thing over the wall for PHP to interpret would be so nice.

 

One other possibility would be to build the PHP "page" in one big string, if that could be eval()d, and do this as the very last thing in index.php so it doesn't matter what kind of "back contamination" there is of the framework. Would that be feasible? I'll have to see if eval() can handle multiline strings. Supposedly you have to surround the string with '?>' and '<?' if it has any HTML in it, but I haven't played with that yet. I'll try to do so tomorrow.

 

Thanks for your thoughts on this.


Edited by MrPhil, 28 April 2016 - 02:43.


#4   burt

burt

    I drink and I know things

  • Community Team
  • 12,449 posts
  • Real Name:G Burton
  • Gender:Male
  • Location:UK/DEV/on

Posted 28 April 2016 - 09:43

Give each file a unique name.

See http://php.net/manua...ion.tempnam.php

This is a signature that appears on all my posts.  It is not specifically aimed at you.

 

IF YOU MAKE A POST REQUESTING HELP...please state the exact version of osCommerce that you are using. THANKS
 
If you are still on the old style osCommerce, it is time to move to Responsive.

 


#5   Jack_mcs

Jack_mcs
  • Members
  • 28,356 posts
  • Real Name:Jack
  • Gender:Male

Posted 28 April 2016 - 16:07

@MrPhil You can't have duplicate file names in the same location so even if you use eval, the file name would be identical, if I understand you correctly. But I don't think you need to be concerned about the file name. Create a master file, say templates.php. For each customer, create a unique file as mentioned previously. It can contain whatever you want. Then add the name of that file to the link to templates.php, like templates.php?file=abc.php and in templates, have code to get that name and load it from the server. If you didn't want the parameter in the url you could create a session variable but that seems a lot of extra work for little gain.



#6   MrPhil

MrPhil
  • Members
  • 6,975 posts
  • Real Name:Phil
  • Gender:Male

Posted 29 April 2016 - 16:37

A status update: I have three ways to do this thing at present...

  1. Write the page PHP/HTML to a uniquely named temporary .php file, and pass the name on redirect to a glue file of fixed name (which includes the temp file). Erase the temp file when done (time delay?). I haven't tried this with a jump address (#target), and may have to do that in Javascript. It would be nice to control the URL when redirecting, but at least the user won't see an ugly temporary name.
  2. Write the page PHP/HTML to a uniquely named temporary .php file, and include() that file in the current (index.php) file. After the include(), unlink() (erase) the file. It appears that any jump address #target on index.php is passed on to the output page, and works. The URL is not modified.
  3. Write the page PHP/HTML to one long string (\n at the end of each line), and eval() it. Again, a jump address #target on index.php is passed on to the output page, and works. The URL is not modified (shows index.php, its UQS, and any jump target). I need to check if // and # comments are terminated by \n or if they need to be banned or converted to /* */ on the fly.

Anyway, #3 certainly appears to be nice and clean. I would prefer it over #2 simply because there is no temporary file to keep track of and delete. I suppose there could be a point where the page source is too big for eval() to handle, but it certainly was no problem for the small but nontrivial page I tried. Note that in all cases, POST and GET variables, if any, would be passed on to the page by hard coding them (programmatically) into the new page source. Any $ signs in PHP code need to be escaped, if they are to be used as variables in the output page.

 

Does anyone see any problem with this approach (#3 preferred at this point)? Might it not work on some PHP levels or some server configurations? Could it easily run into size limitations (for string or for eval input)? It would be nice to be aware of any known gotchas before I look further into template manipulation and seeing if this approach is worth taking any further. Thanks Gary and Jack for your suggestions, and for any further feedback from anyone!


Edited by MrPhil, 29 April 2016 - 16:38.