PDA

View Full Version : First attempt at class in php


smitho
03-31-2008, 02:31 AM
Spent the last couple of weeks learning OOP and understand the tutorials and any example I see but when you first try and apply it to something you are doing it looks very different.

I've got a process where folders on the web server are read using this code (want to keep it simple) which is part of a larger process.


if ($handle = opendir('./images')) {
echo "Directory handle: $handle<br>";
echo "Files:<br><br>";

while (false !== ($file = readdir($handle))) {
if($file != "." && $file != ".." && $file != ".DS_Store"){
echo "$file<br>";
}
}
closedir($handle);
}
Now to use this as a class I've coded this:


class Folder {

var $handle;
var $file;

function __construct($location){

$this->handle = $location;

}


function read_folder($location){

$this->handle = opendir($location);
echo "Directory handle:".$this->handle."<br>";
echo "Files:<br><br>";
while (false !== ($this->file = readdir($this->handle))) {
if($this->file != "." && $this->file != ".." && $this->file != ".DS_Store"){
echo $this->file."<br>";
}
}
}

}
The page that calls the class functions looks like this:


include("FolderClass.php");


$images1 = new Folder("./images");

$images1->read_folder("./images");

Am I coding this correctly? It works but I just want to make sure I'm getting it correct.

davidj
04-01-2008, 08:23 AM
it looks fine to me

pete
04-08-2008, 09:57 PM
You shouldn't be echo'ing out from a method of a class (when talking classes, what you guys refer to as functions should be called methods :)).

You should be returning a string of HTML in your example then use

echo $images1->read_folder("./images");

You would also usually create set/get methods but you have the general idea, just keep on practicing and perhaps get some OOP PHP books.

smitho
04-09-2008, 12:38 AM
Thanks Pete,

You are correct in all the tuts I've gone through it is not a good idea to echo in a class method. If I take out the echo from the class nothing happens. If i change echo to return I only get the first line:

Directory handle:Resource id #5

Any suggestions?

pete
04-09-2008, 07:23 AM
In your example for method read_folder you would do this:

function read_folder($location){

$this->handle = opendir($location);
$sOutput = "Directory handle:".$this->handle."<br>";
$sOutput .= "Files:<br><br>";
while (false !== ($this->file = readdir($this->handle))) {
if($this->file != "." && $this->file != ".." && $this->file != ".DS_Store"){
$sOutput .= $this->file."<br>";
}
}
return $sOutput;
}


If you look at example 1 on this page http://uk3.php.net/function.opendir you will see you should be checking to see whether the location is actually a directory and then also check whether the handle is a valid resource. So
if(is_dir($location)){
if($this->handle = opendir($location)){
....


So the returned value is either a string (list of files) or false, so I would add another method to determine the output, such as $images1->isValid() which would be a boolean and make it easier to ensure the value returned.

You would also perhaps want to return only an array of files from your class method, the HTML should never be part of the class, add any HTML outside the class in the PHP page.

smitho
04-09-2008, 12:03 PM
Greatly appreciated pete,

I mist the if ($handle = opendir('./images')) { from the original example. Iíll give this a go.

Cheers.

smitho
04-17-2008, 12:48 PM
Finally finished the other code I've been working on and I can focus on this again.

I've followed pete's advice but its not returning anything don' t know what I'm missing:


class Folder {

var $handle;
var $file;

function __construct($location){

$this->handle = $location;

}


function read_folder($location){

if(is_dir($location)){
$this->handle = opendir($location);
$sOutput = "Directory handle:".$this->handle."<br>";
$sOutput .= "Files:<br><br>";
while (false !== ($this->file = readdir($this->handle))) {
if($this->file != "." && $this->file != ".." && $this->file != ".DS_Store"){
$sOutput .= $this->file."<br>";
}
}
return $sOutput;
}
}

}

include("FolderClass.php");

$images1 = new Folder("./images");

$images1->read_folder("./images");

pete
04-17-2008, 12:58 PM
Try this:


<?php
class Folder {

var $handle;
var $file;

function __construct($location){
$this->location = $location;
}


function read_folder(){
if(is_dir($this->location)){
$this->handle = opendir($this->location);
$sOutput = "Directory handle:".$this->location."<br>";
$sOutput .= "Files:<br><br>";
while (false !== ($this->file = readdir($this->handle))) {
if($this->file != "." && $this->file != ".." && $this->file != ".DS_Store"){
$sOutput .= $this->file."<br>";
}
}
return $sOutput;
}
}

}
$oImages = new Folder('images/');
echo $oImages->read_folder();
?>

smitho
04-17-2008, 01:31 PM
Thanks pete,

just went over davidj's class example and saw the echo $results.

So this works fine.


include("FolderClass.php");

$images1 = new Folder("./images");

$result = $images1->read_folder("./images");

<body>

<?php


echo $result;


?>

</body>
Cheers.

smitho
04-18-2008, 11:59 AM
This is not as easy as I thought the next step in the process is to take the files in the folder (in this case pdfs) and create a jpg preview of each one.

The code I use normally is :


$justname = substr($file, 0, -4);

$in="images/$file";
$out="preview/$justname.jpg";
$result = exec("/wamp/www/gs/gswin32c.exe -q -dNOPAUSE -dBATCH -sDEVICE=jpeg -sOutputFile=$out $in 2>&1");

Any suggestions on how to combine $images1->read_folder("./images"); to create the preivews would be a great help.

davidj
04-18-2008, 12:07 PM
your gswin32c.exe converts to jpg

doe this work on one file or when you call it manualy

smitho
04-18-2008, 12:41 PM
This will convert each file to jpg.

So if there are 3 pdfs in /images.
There will be 3 jpgs in /hold


if ($handle = opendir('./images')) {
while (false !== ($file = readdir($handle))){
if ($file != "." && $file != ".." && $file != ".DS_Store"){

$justname = substr($file, 0, -4);

$in="images/$file";
$out="hold/$justname.jpg";
$result = exec("/wamp/www/sites/NewsSite/gs/gswin32c.exe -q -dNOPAUSE -dBATCH -sDEVICE=jpeg -sOutputFile=$out $in 2>&1");
}
}
closedir($handle);
}

davidj
04-18-2008, 02:37 PM
cant you loop through the files using a foreach ($array)

smitho
04-19-2008, 12:58 PM
Is there a reason I should try a foreach loop?

I gather you mean something like this. Doesn't work by the way.


if(is_dir('./images')){
if ($handle = opendir('./images')) {
//while (false !== ($file = readdir($handle))){
$file = readdir($handle);
foreach($file as $value){
if ($file != "." && $file != ".." && $file != ".DS_Store"){
echo $file."<br>";
Just a question about the class approach.

If I try and return just the file names by changing the code to this I only get the last file in the folder.

function read_folder($location){

if(is_dir($location)){
if($this->handle = opendir($location)){;
//$sOutput = "Directory handle:".$this->handle."<br>";
//$sOutput = "Files:<br><br>";
while (false !== ($this->file = readdir($this->handle))) {
if($this->file != "." && $this->file != ".." && $this->file != ".DS_Store"){
$sOutput = $this->file."<br>";
if I leave $sOutput .= $this->file."<br>";I get the file names but I also get the following error:

Notice: Undefined variable: sOutput in

davidj
04-19-2008, 10:16 PM
i hav taken what you had and knocked up the following

it is very rough but could be wittled into a nice thingy

its procedual but wont be hard to recreate it using OOP methods.

it will check a dir for images (gif) and create 50% size thumbs (jpg)

should be a doddle to mould it into your own thingy

NOTE: it uses the gd lib in PHP. Do a phpinfo to check its installed


<?php

$path = "C:\wamp\www\projects\\test2\images\\";

if ($handle = opendir('./images')) {

while (false !== ($file = readdir($handle))){


$fileArray[] = $file;

}

closedir($handle);

}
foreach($fileArray as $key => $value){

if ($fileArray[$key] == "." || $fileArray[$key] == ".."){

unset($fileArray[$key]);

}

}

function imagesCreate($filename,$name){

$percent = 0.5;

// Content type
header('Content-type: image/gif');

// Get new dimensions
list($width, $height) = getimagesize($filename);

$new_width = $width * $percent;
$new_height = $height * $percent;

// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromgif($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

// Return
imagejpeg($image_p, $name, 100);

return false;
}

$i=1;

foreach($fileArray as $filename){

$name = "thumb$i.jpg";

imagesCreate($path.$filename,$name);

echo "<img src=\"thumb$i.jpg\" \>";

$i++;
}
?>

pete
04-21-2008, 09:53 AM
This will convert each file to jpg.

So if there are 3 pdfs in /images.
There will be 3 jpgs in /hold


if ($handle = opendir('./images')) {
while (false !== ($file = readdir($handle))){
if ($file != "." && $file != ".." && $file != ".DS_Store"){

$justname = substr($file, 0, -4);

$in="images/$file";
$out="hold/$justname.jpg";
$result = exec("/wamp/www/sites/NewsSite/gs/gswin32c.exe -q -dNOPAUSE -dBATCH -sDEVICE=jpeg -sOutputFile=$out $in 2>&1");
}
}
closedir($handle);
}


Do you also host on Windows? The majority of PHP hosting is unix (usually Redhat/CentOS/FreeBSD). 99% of hosts have ImageMagick installed which is an image conversion software suite, you can find out if it is available and the path by typing in "which convert" in SSH/Telnet.

So if you want to create thumbs from a directory without PHP just do this in SSH on your server:


mkdir thumbs;
for file in *.jpg;
do convert -quality 80 -thumbnail 50%x50% "$file" "thumbs/$file";
done;
In PHP save yourself complex code and simply do:


<?php
$iter = new DirectoryIterator('.');
while ($iter->valid()) {
if(is_file($iter->current()) && getimagesize($iter->current()))
exec("/sw/bin/convert -quality 80 -thumbnail 50%x50% ".$iter->current() ." small".$iter->current());
$iter->next();
}
?>
In the above example the php code above is in the image directory and the thumbs are created with 'small'. appended to the name.

PHP5 has the SPL http://www.php.net/~helly/php/ext/spl/ (http://www.php.net/%7Ehelly/php/ext/spl/) which makes many typical tasks somewhat easier, such as iterating through a directory.

In the above example I have used is_file() which returns true or false, getimagesize() returns an array if the file is an image or false if it is not an image so this is a good way of determining whether you wish to process it or not.

smitho
04-21-2008, 10:54 AM
Thanks pete,

I'm currently doing my dev work on windows (using wamp). I started on a Mac but moved to PC for the moment. I've looked at ImageMagick but don't think its part of wamp. From what I've read ImageMagick uses ghostscript. Is that correct?

In the process I'm testing I have a folder I check and if there are pdfs I create a thumbnail of the pdf and move it out to another folder. Insert all the data into a table and then output a dynamic table of all the pdfs processed.

I'm finding that ghostscript freezes intermittently and I need to re-start the web server to get the process going again. What would be the best way to capture that ghostscript (or any process for that matter) has stopped? The way I can tell it has stopped is by looking in the folder and the thumbnails have stopped being produced.

The more I look into this ImageMagick seems to be the best way but I worry that if my ghostscript process is falling over so to will ImageMagick.

I'll try and get ImageMagick working.

pete
04-21-2008, 11:29 AM
To create a thumbnail of a PDF (the first page) the command in Image Magick is:

convert -thumbnail 200\>x200\> your_pdf[0] mytest.jpg;


That produces a 200 x 200 thumbnail of the first page of your pdf document.
You can pass that command to exec() in PHP but be aware that shell scripts are a much better option for this type of batch processing. When you use PHP you are hammering Apache and using child processes, eating resources (especially on a shared server) that might cause issues.

If you had 1000 pdfs then this might get you thrown off your host, so ideally you would set this up as a cron job to run when most people are sleeping. You would also check to see when the host runs their nightly backups and avoid that time.

As for ghostscript on Windows, I have no experience but I am guessing you are either making a mistake and creating a thumb of every page in the pdf or you need something faster like ImageMagick (also available for Bindows).

If you are a serious PHP developer I would suggest developing on Mac or Linux, not essential but by far preferred.

pete
04-21-2008, 11:32 AM
FYI file.pdf[0,2] creates thumbs of pages 1 and 3, file.pdf[0-3] creates thumbs of pages 1,2,3 and 4.

smitho
04-21-2008, 11:40 AM
Just installed Q16 version or the 16-bits=per-pixel component ImageMagic-6.4.0-3-Q16-windows-dll.exe. will run some test and see how it goes.

Thanks pete.

smitho
04-21-2008, 01:22 PM
ImageMagik seems does a better job of the jpegs (better looking) but I was finding that if i tried to process more than 4 pdfs in one go I would get the following error:

Maximum execution time of 30 seconds exceeded

So I changed the php.ini maximum_execution_time from 30 to 300 and I was able to process 16 pdfs without a problem. I wonder if this was what was causing my problem with ghostsript.

pete
04-21-2008, 02:03 PM
ImageMagik seems does a better job of the jpegs (better looking) but I was finding that if i tried to process more than 4 pdfs in one go I would get the following error:

Maximum execution time of 30 seconds exceeded

So I changed the php.ini maximum_execution_time from 30 to 300 and I was able to process 16 pdfs without a problem. I wonder if this was what was causing my problem with ghostsript.

Probably which is why I mentioned do not use PHP for jobs that you can do without it. PHP isn't meant for batch processing, use a shell script or just command line if you are doing it on your local machine.

On a shared server by doing these kind of processes you are abusing resources. This is why knowing other languages is useful because you can then use the right tool for the right job but I appreciate we are all limited by our knowledge and therefore try to force what we know (in this case PHP) to do everything we need.

smitho
04-23-2008, 11:46 AM
Ok after doing some looking around I found "Day 15 - Task Scheduler" which works with bat files. Am I correct in saying you should be able to create a bat file that reads the files in a set folder and then executes ImageMagic's covert process?

pete
04-23-2008, 11:48 AM
Ok after doing some looking around I found "Day 15 - Task Scheduler" which works with bat files. Am I correct in saying you should be able to create a bat file that reads the files in a set folder and then executes ImageMagic's covert process?

I assume this is a Windows thing? I am guessing it is the equivalent of unix crontab? Since I don't develop on Windows I can't help further but it should work. Usually you would get stuck in and give it a go :wink: