Codeigniter auto autoload models - php

I wan't to write a function which auto autoloads :) models based on files in folder model. So the application has to scan folder for files, grep all .php files, remove . and .. "folders" and place them in autoload['model'] = array
This is my current code in autoload.php file
$dir = './application/models';
$files = scandir($dir);
unset($files[0]);
unset($files[1]);
$mods = '';
foreach ($files as $f){
if(glob('*.php') ){
$mods .= str_replace('.php','',"'".$f."',");
}
}
$autoload['model'] = $mods;
And i'm keep getting errors like
An uncaught Exception was encountered
Type: RuntimeException
Message: Unable to locate the model you have specified: 'admins','categories','companies','countries'
Filename: D:\wamp64\www\myapp\public_html\rest\system\core\Loader.php
Line Number: 344
It looks like the problem is that when i pass array to $autoload variable it threats whole array as one model. Can you guys help me fix my problem.

I would go for something like:
/application/config/autoload.php
autoload['model'] = array('autoload_models');
/application/models/Autoload_models_model.php
class Autoload_models_model extends CI_Model {
public function __construct(){
parent::__construct();
// Scan directory where this (Autoload_models_model.php) file is located
$model_files = scandir(__DIR__);
foreach($model_files as $file){
// Make sure we are not reloading autoload_models_model
// Make sure we have a PHP file
if(
strtolower(explode('.', $file)[0]) !== strtolower(__CLASS__) &&
strtolower(explode('.', $file)[1]) === 'php')
{
$this->load->model(strtolower($file));
}
}
}
}

This is the solution that worked for me. If you find any shorter or nicer code please let me know
$dir = './application/models';
$files = scandir($dir);
$models = array();
foreach ($files as $f){
$file_parts = pathinfo($f);
$file_parts['extension'];
$correct_extension = Array('php');
if(in_array($file_parts['extension'], $correct_extension)){
array_push($models, str_replace('.php','',$f));
}
}
$autoload['model'] = $models;

/* autoload model */
function iteratorFileRegex( $dir, $regex )
{
$files = new FilesystemIterator( $dir );
$files = new RegexIterator( $files, $regex );
$models = array();
foreach ( $files as $file )
{
$models[] = pathinfo( $file, PATHINFO_FILENAME ); // Post_Model
}
return $models;
}
$autoload['model'] = iteratorFileRegex( APPPATH . "models", "/^.*\.(php)$/" );

Related

Downloading a Zip file from a Laravel Nova action

I have some files that I store at /storage/app/public/clientA/files/*.pdf. I have models that I can use to access these, and I want users to be able to download multiple files by selecting them in Nova and then using an action. Here is my code for the action:
public function handle(ActionFields $fields, Collection $models)
{
$files = array();
foreach ($models as $file) {
$path = FileHelper::getPathFromUrl($file->url);
array_push($files, $path);
}
$zip_file = 'myfiles.zip';
$zip = new \ZipArchive();
if ($zip->open($zip_file, \ZipArchive::CREATE | \ZipArchive::OVERWRITE) === true)
{
foreach ($files as $item) {
$zip->addFile(public_path('storage/' . $item), $item);
}
$zip->close();
}
return Action::download($zip_file, $zip_file);
}
Also, here is my code for the getPathFromUrl method:
public static function getPathFromUrl ($url)
{
$path = '';
$url_path = parse_url($url, PHP_URL_PATH);
return substr($url_path, strpos($url_path, "/") + 1);
} // returns the format storage/clientA/files/fileName.pdf
My issue at the moment is that its generating an empty zip file. I'm guessing that my paths are wrong when I try and reference the files, but I don't know how to fix it. I've also tried accessing these locations using Storage::get and found that it can't see the files at valid locations (and yes, I have done Storage:link).
Can anyone give me some insight into what I need to change to my addFile to ensure that these pdfs get added to the zip file?

Function to get files of same name from parent folder

I've created custom elements for WPBakery. In the functions.php file, I currently have the following:
add_action( 'vc_before_init', 'vc_before_init_actions' );
function vc_before_init_actions() {
require_once('vc_elements/text-image/init.php' );
require_once('vc_elements/text/init.php' );
}
However, as I build more custom elements, that list will be huge. What I'm looking to do is load all files named init.php in each vc_elements subfolder.
This is my current folder structure:
vc_elements
text-image
init.php
text
init.php
What's the cleanest way to go about this?
You need to use RecursiveDirectoryIterator to scan the folder and get all files which are named as init.php. Below is the code you can use
add_action( 'vc_before_init', 'vc_before_init_actions' );
function vc_before_init_actions() {
$dir = '/full_path_to_vc_elements';
$files = getFiles($dir, 'init.php');
foreach( $files as $file) {
require_once( $file );
}
}
function getFiles($dir, $match) {
$return = array();
$iti = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
foreach($iti as $file){
if ($file->isDir()) {
continue;
}
if(strpos($file , $match) !== false){
$return[] = $file->getPathname();
}
}
return $return;
}
So in future if you add any init.php file inside the folder, it will automatically be picked by getFiles() and included using require.
What I'm looking to do is load all files named init.php in each
vc_elements subfolder.
Assuming you mean only immediate sub-directorys of "vc_elements" you can use GlobIterator with an "*" as a subdirectory wildcard:
$myInitFiles = new GlobIterator('/path/to/vc_elements/*/init.php');
foreach ($myInitFiles as $file) {
require_once( $myInitFiles->key() );
}
unset($myInitFiles); // release object memory for garbage collection
You can obviously convert this to a more general function if required.
Perhaps something like this would work, assuming that directory only contains sub-directories with the elements you need.
$dir = 'path/to/vc_elements';
// Scan directory for its contents and put in array. Remove possiblity of . or ..
$files = array_diff(scandir($dir), array('..', '.'));
foreach ($files as $file) {
$name = '/path/to/vc_elements/' . $file . '/init.php';
include $name;
}
Not sure what the file structor is for your theme but if you have a folder like inc or int make a file called vc-functions.php in that file do something like this.
add_action( 'vc_before_init', 'vc_before_init_actions' );
function vc_before_init_actions() {
require_once('vc_elements/text-image/init.php' );
require_once('vc_elements/text/init.php' );
}
Then in the functions.php
require get_template_directory() . '/inc/vc-functions.php';

How to remove files that start with a certain prefix from php

I need to delete files that start with a prefix in a certain folder in my Symfony project. I have used the following code to delete for example the files start with p_ (p_example.jpeg), but do not delete them:
Php:
public function exampleAction(){
$Dir = $this->container->getParameter('kernel.root_dir').'/../web/uploads/news/';
$files=glob("'".$Dir."p_*.*'",GLOB_MARK);
foreach($files as $file){
if(is_file($file)){
unlink($file);
}
}
}
I appreciate your help.
Finally, I have resolved it with the following code:
Php:
public function exampleAction(){
$Dir = $this->container->getParameter('kernel.root_dir').'/../web/uploads/news/';
$mask = $Dir."p_*.*";
array_map( "unlink", glob( $mask ) );
}

How to save file details into DB in Laravel 5.1

I am trying to insert the details of an uploaded file into a database table and I am getting the following error:
Fatal error: Call to undefined method Symfony\Component\Finder\SplFileInfo::getClientOriginalName()
How would I get the getClientOriginalName(), getClientOriginalName() and getFilename() of a file in Laravel5?
Below is the code I am using.
public function add()
{
$directory = public_path('xml');
$files = File::allFiles($directory);
foreach ($files as $file) {
$entry = new Xmlentry();
$entry->mime = $file->getClientMimeType();
$entry->original_filename = $file->getClientOriginalName();
$entry->filename = $file->getFilename().'.'.$extension;
$entry->save();
}
}
I'm a bit confused why you have getClientOriginalName() in there because that's aimed at temporary file names that have been uploaded but File::allFiles() is getting files from a directory that already have fixed names.
In addition to my comments above, I wanted to add you can just use the SplFileInfo methods.
I've taken the liberty of removing original file name from the code and correcting the lack of assignment statement for the variable $extension.
To answer your question:
public function add()
{
$directory = public_path('xml');
$files = File::allFiles($directory);
foreach ($files as $file) {
$entry = new Xmlentry();
$entry->mime = $file->getType();
$entry->filename = $file->getFilename(). '.' . $file->getExtension();
$entry->save();
}
}

php glob - scan in subfolders for a file

I have a server with a lot of files inside various folders, sub-folders, and sub-sub-folders.
I'm trying to make a search.php page that would be used to search the whole server for a specific file. If the file is found, then return the location path to display a download link.
Here's what i have so far:
$root = $_SERVER['DOCUMENT_ROOT'];
$search = "test.zip";
$found_files = glob("$root/*/test.zip");
$downloadlink = str_replace("$root/", "", $found_files[0]);
if (!empty($downloadlink)) {
echo "$search";
}
The script is working perfectly if the file is inside the root of my domain name... Now i'm trying to find a way to make it also scan sub-folders and sub-sub-folders but i'm stuck here.
There are 2 ways.
Use glob to do recursive search:
<?php
// Does not support flag GLOB_BRACE
function rglob($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = array_merge(
[],
...[$files, rglob($dir . "/" . basename($pattern), $flags)]
);
}
return $files;
}
// usage: to find the test.zip file recursively
$result = rglob($_SERVER['DOCUMENT_ROOT'] . '/test.zip');
var_dump($result);
// to find the all files that names ends with test.zip
$result = rglob($_SERVER['DOCUMENT_ROOT'] . '/*test.zip');
?>
Use RecursiveDirectoryIterator
<?php
// $regPattern should be using regular expression
function rsearch($folder, $regPattern) {
$dir = new RecursiveDirectoryIterator($folder);
$ite = new RecursiveIteratorIterator($dir);
$files = new RegexIterator($ite, $regPattern, RegexIterator::GET_MATCH);
$fileList = array();
foreach($files as $file) {
$fileList = array_merge($fileList, $file);
}
return $fileList;
}
// usage: to find the test.zip file recursively
$result = rsearch($_SERVER['DOCUMENT_ROOT'], '/.*\/test\.zip/'));
var_dump($result);
?>
RecursiveDirectoryIterator comes with PHP5 while glob is from PHP4. Both can do the job, it's up to you.
I want to provide another simple alternative for cases where you can predict a max depth. You can use a pattern with braces listing all possible subfolder depths.
This example allows 0-3 arbitrary subfolders:
glob("$root/{,*/,*/*/,*/*/*/}test_*.zip", GLOB_BRACE);
Of course the braced pattern could be procedurally generated.
This returns fullpath to the file
function rsearch($folder, $pattern) {
$iti = new RecursiveDirectoryIterator($folder);
foreach(new RecursiveIteratorIterator($iti) as $file){
if(strpos($file , $pattern) !== false){
return $file;
}
}
return false;
}
call the function:
$filepath = rsearch('/home/directory/thisdir/', "/findthisfile.jpg");
And this is returns like:
/home/directory/thisdir/subdir/findthisfile.jpg
You can improve this function to find several files like all jpeg file:
function rsearch($folder, $pattern_array) {
$return = array();
$iti = new RecursiveDirectoryIterator($folder);
foreach(new RecursiveIteratorIterator($iti) as $file){
if (in_array(strtolower(array_pop(explode('.', $file))), $pattern_array)){
$return[] = $file;
}
}
return $return;
}
This can call as:
$filepaths = rsearch('/home/directory/thisdir/', array('jpeg', 'jpg') );
Ref: https://stackoverflow.com/a/1860417/219112
As a full solution for your problem (this was also my problem):
<?php
function rsearch($folder, $pattern) {
$dir = new RecursiveDirectoryIterator($folder);
$ite = new RecursiveIteratorIterator($dir);
$files = new RegexIterator($ite, $pattern, RegexIterator::MATCH);
foreach($files as $file) {
yield $file->getPathName();
}
}
Will get you the full path of the items that you wish to find.
Edit: Thanks to Rousseau Alexandre for pointing out , $pattern must be regular expression.

Categories