PHP FTP Discussions Creating a class and OOP

There are several ways to deal with errors, setting the error on some property of the service is my least favourite, because it is too easy to ignore. Plus you have keep track of it, meaning you’d have to blank it if you try to connect again. Which can also be forgotten, etc.

In general: never solve with state that which can also been solved without state

There are two options that are stateless; return a result object, or throw exceptions.

Return a result object
The result object could look like this:

class FtpConnectionResult
{
    private $isSuccessfull ;
    private $error;

    public function __construct($isSuccessful, $error = '')
    {
        $this->isSuccessfull = $isSuccesul;
        $this->error = $error;
    }

    public function isSuccessful()
    {
        return $this->isSuccessfull;
    }

    public function getError()
    {
        return $this->error;
    }
}

And then the method would look like this:

$this->ftpConn = ftp_connect($this->host);
if (!$this->ftpConn) {
    return new FtpConnectionResult(false, 'Unable to connect');
}

$login = ftp_login($ftpConn,$this->user,$this->password);
if (!$login) {
    return new FtpConnectionResult(false, 'Unable to login to FTP. Invalid username and/or password.');
}

ftp_close($ftpConn);
return new FtpConnectionResult(true, null);

Note the pattern here:

Are we still ok?
– no → return
– yes → continue

Throw exceptions
This looks quite similar but throws exception rather than returning a result object. The main advantage here is that you can’t ignore exceptions, you have to deal with them, whereas you can ignore a result object.

You can use one of the built in exceptions, like RuntimeException, or define your own, like so:

class FtpException extends RuntimeException
{
}

So then FtpException is a specific kind of RuntimeException, one that occurs when there is a problem connecting to an FTP server.

Then the method would look like this:

$this->ftpConn = ftp_connect($this->host);
if (!$this->ftpConn) {
    throw new FtpException('Unable to connect');
}

$login = ftp_login($ftpConn,$this->user,$this->password);
if (!$login) {
    return new FtpException(false, 'Unable to login to FTP. Invalid username and/or password.');
}

ftp_close($ftpConn);

Note the pattern here:

Are we still ok?
– no → throw exception
– yes → continue

Also note that if the connection was successful then it doesn’t return anything. It doesn’t have to. The sheer absence of an exception means the method succeeded.

Lastly, some general remarks on the class:

  • $ftpConn should not be public in your class, it breaks encapsulation
  • Why is the method to connect called ftpconn? Do you ftpconn to an FTP server? Or do you connect to an FTP server?
2 Likes

I was going to suggest the exception method as it uses guard clauses. It eliminates all that if/else the OP posted and forces you to deal with the error.

1 Like

Yes in this case I would personally go for exceptions too. It makes more sense here.

1 Like

How?

I have split them into file class structure→

image

Additionally,

I want to split many things into differeny classes.

Connection is opened ↑ and then close, but when it was successful as shown above there I want to perform some operation that will come from some other class definition. How can I move forward?

@rpkamp gave an example of using exceptions in post #22.

1 Like

Take a step back and try to understand the big picture. You need to let go of some of your earlier assumptions and what not. You seem to be making things much harder than they have to be.

class Ftp
{
    private $conn;
    private $login;

    public function __construct($host,$user,$password)
    {
        $this->conn = ftp_connect($host);
        if (!$this->conn) {
            throw new Exception('Unable to connect');
        }
        $this->login = ftp_login($this->conn,$user,$password);
        if (!$this->login) {
            throw new Exception('Unable to login');
        }
    }
}
try {
    $ftp = new Ftp('host','user','pass');
}
catch  (Exception $e) {
    echo $e->getMessage(); die();
}
// Use $ftp for file transfer or whatever

That is all you need to move forward. There is no need for ‘hey it worked’ messages or status codes or any of that stuff. If your ftp object is created then you can move on and start using it.

Now add a fetch file method to your ftp class and get it working.

3 Likes

Can I ask you one thing. Here we have opened an FTP connection but not yet closed. so when we instantiate a class and its object and when our operation is done it is there we will close the connection?

Well, yes. Closing the connection before you’ve done something with it seems rather … pointless.

2 Likes

I’d suggest closing the connection in a destructor. Building on ahundiak’s code, you could do this:

class Ftp
{
    private $conn;
    private $login;

    public function __construct($host,$user,$password)
    {
        $this->conn = ftp_connect($host);
        if (!$this->conn) {
            throw new Exception('Unable to connect');
        }
        $this->login = ftp_login($this->conn,$user,$password);
        if (!$this->login) {
            throw new Exception('Unable to login');
        }
    }
    public function __destruct()
    {
        ftp_close($this->conn);
    }
}
try {
    $ftp = new Ftp('host','user','pass');
}
catch  (Exception $e) {
    echo $e->getMessage(); die();
}
// Use $ftp for file transfer or whatever

The destructor method will be called as soon as there are no other references to the object, which means your ftp connection would automatically close itself at just the right time without you having to do any other special handling.

1 Like

Kudos! and Thanks to you.

After establishing your version. I also tried to use the ftp_put function.4

try {
  $newconn = new FtpConnection('198.57.247.176',
                 '[email protected]',
                 '##');
}
catch  (Exception $e) {
  echo $e->getMessage(); die();
}

$filename = "message.txt";
$source = getcwd()."/".$filename;
// echo $source;
$destination=getcwd()."/"."ftpsend/";
// echo $destination;
$upload = ftp_put($newconn->conn,$destination,$source, FTP_BINARY);

But that is throwing a warning. How should I proceed:

Warning : ftp_put(): Can’t open that file: No such file or directory in /home1/

$upload = ftp_put($newconn->conn,$destination,$source, FTP_BINARY);

So which part of ftp_put has that issue?
I tried many threads on StackOverflow: From nowhere did I get any clue where to troubleshoot.

image

The error doesn’t say that there is no file on the server, but the error says that there is no such file in index.php on line 30 and line 30 is where we have to use the ftp_put function.

The file actually exists on the server.

The relevant live link.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.