I have a normal setup for MVC: domain.com/{controller}/{method}/{param}.
I have these 2 functions, the first works and the other one doesn't:
private function _getUserWords()
{
return file(URL . 'public/txt/words.txt');
}
private function _getUserSentences()
{
$file = URL . 'public/txt/' . strtolower($this->view->randomWord) . '.txt';
echo $file;
return file($file);
}
Now the first one actually includes the file, but using the second one, it trys to include the 'public' controller and execute the 'txt' method. I can't seem to figure out why this is, any ideas?
Related
I am trying to delete pdf files from a folder. I have written the delete_files function as follows
public function delete_files($company_id)
{
$this->load->model('search_model');
$company = $this->search_model->get_company($company_id);
$username = $company[0]['username'];
$path=$this->config->base_url('/uploads/'.$username . '/' . 'uploaded');
$this->load->helper("file"); // load the helper
delete_files($path, true); // delete all files/folders
}
when i did echo $path; it shows the right path where i want the files deleted but when i run the entire function nothing happens and i just get a white screen.
You need to use path to file and not resource locator.
$path = FCPATH . "uploads/$username/uploaded";
try this code
Use
$path = FCPATH . "uploads/$username/uploaded";
unset($path);
I am uploading an image and while storing the image, I am setting the Filename like 'assets/Uploads/54f092af271b9.png' but after saving, the Filename fields loses some part. It becomes 'assets/54f092af271b9.png' losing the "Uploads/" directory altogether. Is it supposed to happen?
Here's the codes:
<?php
$img = new Image();
$baseName = pathinfo($file, PATHINFO_BASENAME);
$fileName = 'assets/Uploads/' . $baseName;
var_dump($fileName);
$img->Name = $baseName;
$img->Filename = $fileName;
$img->OwnerID = ($memberID = Member::currentUserID()) ? $memberID : 0;
$img->write();
var_dump($img->Filename); exit;
Output is:
assets/Uploads/54f092af271b9.png
assets/54f092af271b9.png'
Any ideas?
I was able to replicate the issue with the code you provided. After a bit of digging around, here is what I found.
It all starts in the onAfterWrite function in File class (which Image extends). Fired after you called write (obviously), this calls updateFilesystem where this line sets the Filename property with the result of the getRelativePath function call.
At the time of writing, getRelativePath looks like this:
public function getRelativePath() {
if($this->ParentID) {
// Don't use the cache, the parent has just been changed
$p = DataObject::get_by_id('Folder', $this->ParentID, false);
if($p && $p->exists()) return $p->getRelativePath() . $this->getField("Name");
else return ASSETS_DIR . "/" . $this->getField("Name");
} else if($this->getField("Name")) {
return ASSETS_DIR . "/" . $this->getField("Name");
} else {
return ASSETS_DIR;
}
}
Looking at that code, the issue you have comes from ParentID not being set on your record when you wrote it to the DB so the second condition is run instead returning the result of ASSETS_DIR . "/" . $this->getField("Name").
So that is the problem addressed, now for a solution. Silverstripe wants a parent folder, you've just got to give it one.
Fortunately there is a great little function on the Folder class called find_or_make which does what the name says, either finds the folder record in the filesystem and DB or it will generate it for you.
Note: In my own testing, while I had an "Uploads" folder, I did not have a corresponding DB record so this function wrote that for me an returned the result.
I then used the result to give the image I was writing to the DB a ParentID and it made the second var_dump return the same value as the first.
This is all you need to add to your code before calling write:
$parentFolder = Folder::find_or_make('Uploads');
$img->setParentID($parentFolder->ID);
I am trying to debug some scripts that I've done that don't work.
I want to implement the very basic logging (I mean log files) function that I use in the main page script in my class files.
However it doesn't work, for example these simple lines:
if ($file = fopen('C:/wamp/www/xxxx/Logs/General/' . date('Ymd') . '.log', 'a+') {
fputs($file, "[" . date('d/m/Y - H:i:s') . "]\t" . "[" . $type ."]\t" . "[" . $author . "]\t" . $message . "\r\n");
fclose($file);
}
else
{
return false;
}
Work perfectly if I put them in a php function included at the top of my main page (for example in a log.php file).
Howevr they don't work at all if they are in a class method:
public function __contruct(array $connectionArgs)
{
if ($file = fopen('C:/wamp/www/xxxx/Logs/General/' . date('Ymd') . '.log', 'a')) {
fwrite($file, "test");
fclose($file);
}
else
{
die("fail");
}
I am quite new to OOP so I guess it has something to do with the way of calling such function into a class?
It shoudln't be a different if you're putting your logger in class definition or in function code. I assume that you're doing something wrong or maybe you have some error.
Here this is working example
Class Logger
{
const PATH_TO_LOGS_DIRECTORY = 'C:/wamp/www/xxxx/Logs/General/';
const FILE_DATE_SUFFIX = 'Ymd';
private $handle;
public function log($what) {
$this->openFile();
fwrite($this->handle, $what . PHP_EOL);
}
protected function openFile() {
if ($this->handle === null) {
$this->handle = fopen(self::PATH_TO_LOGS_DIRECTORY . date(self::FILE_DATE_SUFFIX) . '.log', 'a');
if ($this->handle === false) {
throw new RuntimeException('Cannot open log file');
}
}
register_shutdown_function(array($this, 'close'));
}
public function close() {
if($this->handle !== null) {
fclose($this->handle);
}
}
}
Few extra things that you should care of :
don't open file till you want to log something. When you're not logging stuff you don't need to reach the file and seek to end of file.. It's called Lazy Initialiation. When you want to log something they you're opening file
in this demo class I'm using a small trick, normally when you're shuttingdown application you should close the log file, (call fclose()), but then you have remember that, and then if you have exception you have to handle that also. But you can use register_shutdown_function and PHP will always call that function on the end of php script
take a look on PSR-3 (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) - PHP group is trying to standarize the logging systems so there is no need to to write your own interface to handle
it's good to pass date string (timestamp or DateTime object event better a param to constructor. You should pass dependency, not expect them
I'm building a script that got a static class used to load few things including files and views.
class load
{
public static function view($file_path, $area)
{
debug::log('getting view <b>' . $area . $file_path . '</b>.');
ob_start();
self::file($file_path, 'areas/' . $area . '/views');
debug::log('flushing view <b>' . $area . $file_path . '</b>.');
eturn ob_get_clean();
}
public static function file($file, $folder)
{
if(is_file($file_path = ROOT . '/' . $folder . '/' . $file))
{
if(require_once $file_path)
{
debug::log('file <b>' . $file_path . '</b> included.');
return true;
}
}
else
debug::kill('requested file <b>' . $file_path . '</b> does not exist.');
}
}
In the controller Im calling the view method to get a view:
$html = load::view('public', 'path/to/view/file.php');
Obviously, Im not able to access the variables from the controller at the view file using this practice, so I did a small modification on the view class to capture the vars:
public static function view($file_path, $area, $vars = array())
And added the following lines of codes to get the keys into vars:
while(list($n_list_var,$v_list_var)=each($vars))
$$n_list_var = $v_list_var;
But again I can't access the vars since Im using a method to load a file.
I have a method to load the files because I wanna test and log each file include attempt and not repeat the code every time I need include a file. And I have the loader view inside the loader class so I have all the methods of this kind together. Should I give up on using a class to load files? Should I use the loader view method on a extendable class from my controller?
Instead of going ahead and modify my entire script I would like to hear some opinions ... what would be the best practice to go? Or is there a way to solve my problem? Maybe using __set and __get magic methods?
Thanks,
Why not just pass a $vars argument to load::file() and extract( $vars ) (possibly moving the vars you use inside file() into class variables to prevent them from being overwritten)?
I'm suggesting using extract() instead of:
while(list($n_list_var,$v_list_var)=each($vars))
$$n_list_var = $v_list_var;
By the way, it would be a good idea to name your class Load.
In my Product Class, there is a function called pictures() which returns the file address of the picture of a product. It's something like this:
public function picture()
{
$file = "images/pictures/products/" . $this->id . ".png";
if(file_exists($file))
return $file;
else
return false;
}
It works fine when running the code on the administration area of the website (which is located on /admin/ directory)
But when I call this function from the index.php which is not on the /admin/ directory it always returns false. What should I do? The only way I figured to solve this is by creating a parameter on the picture() function, like: picture($directory_prefix) then that way I'll call the function with picture("/admin/"). But there's gotta be a better way than this...
Place your resources in a directory under the web root. Then the path would be:
$file = $_SERVER['HTTP_HOST']."/images/pictures/products/" . $this->id . ".png";