database icon indicating copy to clipboard operation
database copied to clipboard

It can't access files that should have been created

Open guilhermeaiolfi opened this issue 7 years ago • 2 comments

Version: dev-master

Bug Description

It throws failed to open stream: No such file or directory in \database-explorer\vendor\nette\caching\src\Caching\Storages\FileStorage.php on 137 line. It creates a _Nette.Database.Structure.0f6c8930e1b455996fff524bc1a51b4b folder and a _07414f4e15ca943e6cde032dec85d92f file inside that folder. But for some reason, it doesn't create the other folder and file and tries to access it afterwards.

Steps To Reproduce

The only think I've done was to create the following index.php file.

<?php
include('vendor/autoload.php');

use Nette\Database\Connection;

$tempDir = "./cache/database-explorer";
$storage = new Nette\Caching\Storages\FileStorage($tempDir);
$connection = new Nette\Database\Connection("pgsql:host=localhost;dbname=DBNAME;options='--client_encoding=utf8'", "postgres", "PASSWORD");


$structure = new Nette\Database\Structure($connection, $storage);
$conventions = new Nette\Database\Conventions\DiscoveredConventions($structure);
$context = new Nette\Database\Context($connection, $structure, $conventions, $storage);

$rows = $context->table('notifications');
foreach ($rows as $row) {
	echo $row->timestamp;
}

Expected Behavior

No errors.

Possible Solution

Only evaluating the library. I really like the simplicity of the idea behind it. Congrats to the developers that came up with it.

guilhermeaiolfi avatar Sep 17 '18 13:09 guilhermeaiolfi

So, exactly 2 years later I came back to give it another try and the same error occurs. Different PC, PHP version, but same error. Is this project maintained yet?

guilhermeaiolfi avatar Sep 18 '20 14:09 guilhermeaiolfi

Changing FileStorage.php:137 to:

$handle = @fopen($cacheFile, 'c+b'); // added '@'

makes the error go away, but I guess we lose the cache.

guilhermeaiolfi avatar Sep 18 '20 14:09 guilhermeaiolfi

am also receiving the same error, and the only way I can suppress the error is by turning off the E_WARNING every time I use the explore functionality which I personally think it's a bad idea, is there a workaround to suppress the error without hiding all warnings and or without losing the cache, here is my implementation

<?php

use Nette\Database\Explorer;
use Nette\Database\Structure;
use Nette\Database\Connection;
use Nette\Caching\Storages\FileStorage;
use Nette\Database\Conventions\DiscoveredConventions;

class DB{

    private $storage;
    private $structure;
    private $conventions;

    function __construct(){
        $this->storage = new FileStorage('cache/db');
        $this->structure = new Structure($this->conn(), $this->storage);
        $this->conventions = new DiscoveredConventions($this->structure);
    }

    function conn(){
        $engine = config('db_engine');

        switch ($engine):
            
            case 'mysql':
                $hostname = config('db_host');
                $username = config('db_user');
                $password = config('db_pass');
                $database = config('db_name');

                $connector = "mysql:host=$hostname;dbname=$database";
            
                return new Connection(
                    $connector, $username, $password
                ); break;

        endswitch;
    }

    function explore(){
        error_reporting(E_ALL & ~E_WARNING);
        return new Explorer($this->conn(), $this->structure, $this->conventions, $this->storage);
    }


}

ibnsultan avatar Dec 05 '23 18:12 ibnsultan

Couldn't the problem be the use of relative path? I.e. use for example FileStorage(__DIR__ . '/cache/db')

dg avatar Dec 05 '23 18:12 dg

Couldn't the problem be the use of relative path? I.e. use for example FileStorage(__DIR__ . '/cache/db')

I don't think that's the case because

  • with FileStorage(__DIR__ . '/cache/db') the error is Directory '/myRoot/project\core/cache/db' not found and the error occurs from the constructor, and this is because the cache folder is on the project basepath and DIR is relative to the execution file meanwhile cache folder is at '/myRoot/project\cache/db
public function __construct(string $dir, ?Journal $journal = null)
    {
        if (!is_dir($dir)) {
            throw new Nette\DirectoryNotFoundException("Directory '$dir' not found.");  # <<< error is thrown on this line
        }
 
        $this->dir = $dir;
        $this->journal = $journal;
 
        if (mt_rand() / mt_getrandmax() < static::$gcProbability) {
            $this->clean([]);
        }
    }
  • with FileStorage('cache/db'); everything works fine, the cache folders and files are also created successfully, the error occurs while trying to lock the cache file fopen(cache/db/_Nette.Database.cacheCode/_cacheRef): Failed to open stream: No such file or directory
public function lock(string $key): void
{
    $cacheFile = $this->getCacheFile($key);
    if (!is_dir($dir = dirname($cacheFile))) {
	    @mkdir($dir); // @ - directory may already exist
    }
    
    $handle = fopen($cacheFile, 'c+b');     # <<< error happens here
    if (!$handle) {
	    return;
    }
    
    $this->locks[$key] = $handle;
    flock($handle, LOCK_EX);
}

ibnsultan avatar Dec 05 '23 19:12 ibnsultan

I used FileStorage(getcwd().'/cache/db'); everything works fine now, it also seems to be working fine with absolute path thanks @dg

ibnsultan avatar Dec 05 '23 19:12 ibnsultan