I have been trying to figure out a way to load models from different directory other than "application/models" directory.
I want to load my model from "application/modules".
I have tried the instructions by extending CI_Loader by following instructions provided in
http://ellislab.com/forums/viewthread/103276/#
but it is giving me error "Unable to locate the specified class: Model.php" whereas my core "Model.php" is there under "system/core" folder.
Even ,I have also tried to load model using
$this->load->model (APPPATH.'modules/mymodel.php');
but no success.
UPDATE:
I want my model loader to behave like this :
$this->load->module('mymodel')
and
$this->mymodel->mymodelmethod() !!
NOT like: $this->load->models('mymodel')
Is there any way i could load models from outside the "application/modules" folder ?
Please advise .Thanks
The problem is that the code you reference is for an older version of codeigniter. In older versions of codeigniter the CI_Model class was named Model. As the class Model doesn't exist in the latest version of php you are getting the error:
Unable to locate the specified class: Model.php
The part of the code where this is happening is towards the end (line 114):
if ( ! class_exists('Model'))
{
load_class('Model', FALSE);
}
If you check your system/core/Loader.php you will see that in the version of codeigniter you are using this has been replaced with:
if ( ! class_exists('CI_Model'))
{
load_class('Model', 'core');
}
You need to re-write the MY_Loader.php to make it compatible with the version of codeigniter you are using, presumably 2.1.
The best way to do this would be to grab the Codeigniter 2.1 version of the core Loader.php and use the model() method from it as a base for re-writing your MY_Loader.php.
Something to bare in mind when re-writing your MY_Loader.php is that constructors also changed in later versions of codeigniter, so your MY_Loader class should look something like this:
class MY_Loader extends CI_Loader {
function __construct()
{
parent::__construct();
}
public function model($model, $name = '', $db_conn = FALSE)
{
...
}
}
More details on extending core classes can be found in the Codeigniter Documentation
UPDATE
I noticed you changed your functionality, so I updated the answer. You can create a whole new loader and base it off the core CI_Model class, although it seems like a lot of effort when you could just extend the model loader and be done.
class MY_Loader extends CI_Loader {
protected $_ci_module_paths = array();
protected $_ci_modules = array();
function __construct()
{
parent::__construct();
$this->_ci_module_paths = array(APPPATH);
}
public function initialize()
{
$this->_ci_classes = array();
$this->_ci_loaded_files = array();
$this->_ci_models = array();
$this->_ci_modules = array();
$this->_base_classes =& is_loaded();
$this->_ci_autoloader();
return $this;
}
public function module($module, $name = '', $db_conn = FALSE)
{
if (is_array($module))
{
foreach ($module as $babe)
{
$this->$module($babe);
}
return;
}
if ($module == '')
{
return;
}
$path = '';
// Is the $module in a sub-folder? If so, parse out the filename and path.
if (($last_slash = strrpos($module, '/')) !== FALSE)
{
// The path is in front of the last slash
$path = substr($module, 0, $last_slash + 1);
// And the module name behind it
$module = substr($module, $last_slash + 1);
}
if ($name == '')
{
$name = $module;
}
if (in_array($name, $this->_ci_modules, TRUE))
{
return;
}
$CI =& get_instance();
if (isset($CI->$name))
{
show_error('The module name you are loading is the name of a resource that is already being used: '.$name);
}
$module = strtolower($module);
foreach ($this->_ci_module_paths as $mod_path)
{
if ( ! file_exists($mod_path.'modules/'.$path.$module.'.php'))
{
continue;
}
if ($db_conn !== FALSE AND ! class_exists('CI_DB'))
{
if ($db_conn === TRUE)
{
$db_conn = '';
}
$CI->load->database($db_conn, FALSE, TRUE);
}
if ( ! class_exists('CI_Model'))
{
load_class('Model', 'core');
}
require_once($mod_path.'modules/'.$path.$module.'.php');
$module = ucfirst($module);
$CI->$name = new $module();
$this->_ci_modules[] = $name;
return;
}
// couldn't find the model
show_error('Unable to locate the module you have specified: '.$module);
}
public function add_package_path($path, $view_cascade=TRUE)
{
$path = rtrim($path, '/').'/';
array_unshift($this->_ci_library_paths, $path);
array_unshift($this->_ci_model_paths, $path);
array_unshift($this->_ci_module_paths, $path);
array_unshift($this->_ci_helper_paths, $path);
$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
// Add config file path
$config =& $this->_ci_get_component('config');
array_unshift($config->_config_paths, $path);
}
public function remove_package_path($path = '', $remove_config_path = TRUE)
{
$config =& $this->_ci_get_component('config');
if ($path == '')
{
$void = array_shift($this->_ci_library_paths);
$void = array_shift($this->_ci_model_paths);
$void = array_shift($this->_ci_module_paths);
$void = array_shift($this->_ci_helper_paths);
$void = array_shift($this->_ci_view_paths);
$void = array_shift($config->_config_paths);
}
else
{
$path = rtrim($path, '/').'/';
foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_module_paths', '_ci_helper_paths') as $var)
{
if (($key = array_search($path, $this->{$var})) !== FALSE)
{
unset($this->{$var}[$key]);
}
}
if (isset($this->_ci_view_paths[$path.'views/']))
{
unset($this->_ci_view_paths[$path.'views/']);
}
if (($key = array_search($path, $config->_config_paths)) !== FALSE)
{
unset($config->_config_paths[$key]);
}
}
// make sure the application default paths are still in the array
$this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));
$this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));
$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
$this->_ci_module_paths = array_unique(array_merge($this->_ci_module_paths, array(APPPATH)));
$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
}
private function _ci_autoloader()
{
if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
}
else
{
include(APPPATH.'config/autoload.php');
}
if ( ! isset($autoload))
{
return FALSE;
}
// Autoload packages
if (isset($autoload['packages']))
{
foreach ($autoload['packages'] as $package_path)
{
$this->add_package_path($package_path);
}
}
// Load any custom config file
if (count($autoload['config']) > 0)
{
$CI =& get_instance();
foreach ($autoload['config'] as $key => $val)
{
$CI->config->load($val);
}
}
// Autoload helpers and languages
foreach (array('helper', 'language') as $type)
{
if (isset($autoload[$type]) AND count($autoload[$type]) > 0)
{
$this->$type($autoload[$type]);
}
}
// A little tweak to remain backward compatible
// The $autoload['core'] item was deprecated
if ( ! isset($autoload['libraries']) AND isset($autoload['core']))
{
$autoload['libraries'] = $autoload['core'];
}
// Load libraries
if (isset($autoload['libraries']) AND count($autoload['libraries']) > 0)
{
// Load the database driver.
if (in_array('database', $autoload['libraries']))
{
$this->database();
$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));
}
// Load all other libraries
foreach ($autoload['libraries'] as $item)
{
$this->library($item);
}
}
// Autoload models
if (isset($autoload['model']))
{
$this->model($autoload['model']);
}
// Autoload modules
if (isset($autoload['module']))
{
$this->module($autoload['module']);
}
}
}
You can use the above in your controller via:
$this->load->module('test_module');
$this->test_module->method();
If i am getting your problem correctly , you have to initialize the instance of CI.
Example :-
In your external file do this :-
class modules
{
var $CI;
function __construct()
{
$this->CI =& get_instance();
}
function retrieve_data()
{
// Load Model
$this->CI->load->model('YOUR MODEL NAME'); // Give the name of your model that you want to laod
}
}
Hope it helps you :)
As far as i understand your question the answer lies here.
Moduler Extension
download it and install according to the instructions. then you can simply access any thing with these steps.
In your controller load the module like this.
$this->load->module('pages');
Make sure you have a directory Modules under application. And your Module pages should exist there. Pages module can have controller , models , views , helpers , config and libraries etc.
Now you need to call model. Here is how you can do it.
$this->pages->model->test_model->get_test_data();
Also you should note that loading module loads all the resources.
If nothing works, try this
public function setPackagePaths($path, $view_cascade=TRUE, $model_cascade=TRUE, $library_cascade=TRUE, $helper_cascade=TRUE) {
$path = rtrim($path, '/').'/';
///$this->_ci_view_paths = $this->_ci_library_paths = $this->_ci_model_paths = array();
$this->_ci_library_paths = array($path.'libraries/' => $library_cascade) + $this->_ci_library_paths ;
$this->_ci_helper_paths = array($path.'helpers/' => $helper_cascade) + $this->_ci_helper_paths ;
$this->_ci_model_paths = array($path.'models/' => $model_cascade) + $this->_ci_model_paths ;
$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;
// Add config file path
$config =& $this->_ci_get_component('config');
array_unshift($config->_config_paths, $path);
}
Its a hardcore way to update this function to Loader Class. But works fine.
Related
I am trying to load (include file) the GetRiskSummaryCommandHandler.php (GetRiskSummary\CommandHandler) at runtime dynamically, while resolving Route api/risks to HandleCommand (of class CommandHandler) method.
How can I do this? If not can I modify any taken approach including modifying autoloader?
My api class snippet looks like this:
API.php
<?php
abstract class API
{
public function processRequest()
{
$id1 = $this->requestObj->id1;
//$id2 = $this->requestObj->id2;
$endpoint1 = $this->requestObj->endpoint1;
$endpoint2 = $this->requestObj->endpoint2;
$isDestination = in_array($id1, ['first', 'prev', 'next', 'last']);
$numSetEndpoints = (int)isset($endpoint1) + (int)isset($endpoint2);
switch($numSetEndpoints)
{
case 0:
if ($isDestination)
return json_decode($this->_response("No Endpoint: ", $endpoint1));
return json_decode($this->_response("ProjectAIM API"));
case 1:
$className = $endpoint1.'Controller';
break;
case 2:
$className = $endpoint2.'Controller';
break;
}
$class = "GetRiskSummaryCommandHandler";
$method = "HandleCommand";
if (class_exists($class))
{
if (method_exists($class, $method))
{
$response = (new $class($this->requestObj))->{$method}($this->requestObj);
if ($response['Succeeded'] == false)
{
return $response['Result'];
}
else if ($response['Succeeded'] == true)
{
header("Content-Type: application/json");
return $this->_response($response);
}
else if ($response['Result'])
{
header("Content-Type: text/html");
return $this->_response($response);
}
}
}
}
**Command Handler Snippet, uses a Route Attiribute
GetRiskSummaryCommandHandler.php
<?php
namespace GetRiskSummary;
use Infrastructure\CommandHandler;
class GetRiskSummaryCommandHandler extends CommandHandler
{
#[Route("/api/risks", methods: ["GET"])]
public function HandleCommand()
{
$qb = $this->getEntityManager()
->createQueryBuilder();
$qb->select('*')
->from('Risks', 'Risks')
->orderBy('RiskID', 'DESC');
$query = $qb->getQuery();
return $query->getResult();
}
}
Autoloader.php
<?php
namespace Autoloader;
class Autoloader
{
private static function rglob($pattern, $flags = 0) {
$files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
$files = array_merge($files, self::rglob($dir.'/'.basename($pattern), $flags));
}
return $files;
}
public static function ClassLoader($path)
{
$pathParts = explode("\\", $path);
$path = $pathParts[array_key_last($pathParts)];
$matches = self::rglob("*/$path*");
foreach ($matches as $name)
{
$filePath = realpath($name);
if (file_exists($filePath))
include $filePath;
}
}
}
spl_autoload_register("AutoLoader\AutoLoader::ClassLoader");
I think the biggest missing feature of PHP Attributes would be that as far as I'm aware PHP Attributes are static and aren't evaluated at runtime. They are just glorified comments.
If it was true, we could do some truly amazing things like non-intrusively attaching pre/post-processing functions, just like what you wrote.
They work just like in symfony or doctrine. You can't use variables in them and you must write your own code to search your php class tree for attributes in the code and use php reflection to obtain the information and run the attributes.
To be honest it's pretty disappointing, although maybe it's just the first step that will be fixed in later versions of PHP.
But for now, I think what you're asking for is impossible. Because they are not running dynamically like you appear to be asking.
I am new to laravel and would like to fetch list of all controllers and list of action in that controller.
Just want to know if there is a way to get a list of all Controllers as well as all their Methods by code?
Thanks,
DJ
By how you are explaining the need for you to know the controller actions, it seems that the actions are already mapped to routes, which means you can use the routes to get the list of mapped controllers and actions. The following code will generate an array of the registered route controller actions:
$controllers = [];
foreach (Route::getRoutes()->getRoutes() as $route)
{
$action = $route->getAction();
if (array_key_exists('controller', $action))
{
// You can also use explode('#', $action['controller']); here
// to separate the class name from the method
$controllers[] = $action['controller'];
}
}
This will ignore routes that have Closures mapped, which you don't need. Mind you, you might need to filter out any matches from routes registered by third party packages.
That worked for me.
Extracting all controllers (App\Http\Controllers)
$controllers = require_once base_path('vendor/composer/autoload_classmap.php');
$controllers = array_keys($controllers);
$controllers = array_filter($controllers, function ($controller) {
return strpos($controller, 'App\Http\Controllers') !== false;
});
$controllers = array_map(function ($controller) {
return str_replace('App\Http\Controllers\\', '', $controller);
}, $controllers);
dd($controllers);
Extracting all methods in a specific controller using ReflectionClass
$namespace = "App\Http\Controllers";
$controller = "TestController";
$controller_class = new ReflectionClass($namespace.'\\'.$controller);
$controller_methods = $controller_class->getMethods(ReflectionMethod::IS_PUBLIC);
dd($controller_methods);
One catch though. You may need to run composer dump-autoload after creating a controller.
Old code:
public static function Controllers()
{
$controllers = require_once base_path('vendor/composer/autoload_classmap.php');
$controllers = array_keys($controllers);
$controllers = array_filter($controllers, function ($controller) {
return strpos($controller, 'App\Http\Controllers') !== false;
});
$controllers = array_map(function ($controller) {
return str_replace('App\Http\Controllers\\', '', $controller);
}, $controllers);
return $controllers;
}
Edited:
This Code is much better:
public static function Controllers()
{
$classes = array_filter(get_declared_classes(), function ($class) {
$isController = substr($class, -10) == 'Controller';
$isNotPlainController = $isController && substr($class, -11) != '\Controller';
return $isNotPlainController;
});
//Optional: to clear controller name from its namespace
$controllers=array_map(function ($controller){
return last(explode('\\',$controller));
},$classes);
//Optional: to reset keys of array to start from 0,1,2,...etc
$controllers = array_values($controllers);
return $controllers;
}
Try running this:
$classes = get_declared_classes();
foreach ($classes as $class) {
if (is_subclass_of($class, 'App\Http\Controllers\Controller')) {
echo $class . '<br />';
$methods = get_class_methods($class);
foreach ($methods as $method)
echo '--- ' . $method . '<br />';
}
}
It should output all your controllers (anything inherited from the Controller class) and their methods.
I'm not sure how to tell which ones of the methods are actual controller actions though. If you use controller routes that would be the ones starting with "get", "post" or "any", but if you're using direct links that's not the case.
Try this
$controllers = [];
$i=0;
foreach (Route::getRoutes()->getRoutes() as $route)
{
$action = $route->getAction();
if (array_key_exists('controller', $action))
{
$_action = explode('#',$action['controller']);
$_namespaces_chunks = explode('\\',$_action[0]);
$controllers[$i]['controller'] = end($_namespaces_chunks);
$controllers[$i]['action'] = end($_action);
$controllers[$i]['namespace'] = $action['controller'];
$controllers[$i]['route'] = $route;
}
$i++;
}
dump($controllers);
Grep can be used to print a list of all actions per controller on unix systems.
Open a console in the laravel project root and execute the following command:
grep "public function" app/Http/Controllers/* -r
I'm trying to make a prototype of a simple plugin system I plan on implementing into one of my projects. I have 4 files:
Index.php
Plugins/__BASE.php
Plugins/Sample.php
The index file checks if the 'oncall' method belongs to a class in the Plugins folder using functions I defined in the Plugins class (__BASE.php). If it does exist, it will execute it.
require_once 'Plugins/__BASE.PHP';
$func = 'oncall';
$plugins = new Plugins();
if($plugins->IsPluginMethod($func)) {
$obj = $plugins->GetObject($func);
call_user_func(array($obj, $func));
}
else
echo "'$func' isn't part of a plugin!";
__BASE.php is the base plugin class which all of the plugins will extend. It has two methods: IsPluginMethod() and GetObject(). IsPluginMethod checks if the method name supplied belongs to a class and GetObject returns an instance of the class the method belongs to.
class Plugins {
public $age = "100";
public function IsPluginMethod($func) {
foreach(glob('*.php') as, $file) {
if($file != '__BASE.php') {
require_once $file;
$class = basename($file, '.php');
if(class_exists($class)) {
$obj = new $class;
if(method_exists($obj, $func))
return true;
else
return false;
}
}
}
}
public function GetObject($func) {
foreach(glob('*.php') as $file) {
if($file != '__BASE.php') {
require_once $file;
$class = basename($file, '.php');
if(class_exists($class)) {
$obj = new $class;
return $obj;
}
}
}
}
}
Sample.php is a sample plugin which prints $this->age which is defined in the Plugins class.
class Sample extends Plugins {
public function oncall() {
echo "Age: {$this->age}";
}
}
This is what I see in index.php:
'oncall' isn't part of a plugin!
Can anyone help? Thanks.
In __BASE.php file change (glob('*.php') to glob('Plugins/*.php')
I am using a Spotify library called MetaTune and was able to do this easily in CodeIgniter but with Yii there have been some teething issues however currently it has started saying:
Fatal error: Call to undefined method stdClass::searchTrack() in ....public_html/Yii/news/protected/controllers/NewsController.php on line 67
Howevever, the the function is there. The files in this library all have a .class.php suffix (e.g. MetaTune.class.php) and the libray files are all stored in:
yii/application/protected/vendors/Metatune
With Codeigniter I made an additional spotify.php outside of the folder and autoloaded that to my controller, but im not sure if this is necessary.
I have loaded it in my config.php with:
'import'=>array(
'application.models.*',
'application.components.*',
'application.vendors.metatune.*',
),
Here is the Controller code:
public function actionView($id)
{
$model=$this->loadModel($id);
$spotify = MetaTune::getSomething();
$hello = $model->title;
Yii::import('application.vendors.metatune.MetaTune');
$spotify->autoAddTracksToPlayButton = true; // Will add all searches for tracks into a list.
$spotify->playButtonHeight = 330; // For viewing the entire playlist
$spotify->playButtonTheme = "dark"; // Changing theme
$spotify->playButtonView = "coverart"; // Changing view
try
{
$tracks = $spotify->searchTrack($hello);
$tracks = $spotify->getPlayButtonAutoGenerated($hello);
}
catch (MetaTuneException $ex)
{
die("<pre>Error\n" . $ex . "</pre>");
}
$song = 'tracks';
$this->render('view',array(
'model'=>$this->loadModel($id),
));
}
Please also see the code below where it has a function called getInstance which doesnt work well with Yii for some reason and Im not sure if I can change this as I used this to import MetaTune into the CodeIgniter controller without any issues.
Just a part of the MetaTune.class.php code:
Yii::import('application.vendors.metatune.Artist');
Yii::import('application.vendors.metatune.Album');
Yii::import('application.vendors.metatune.Track');
Yii::import('application.vendors.metatune.CacheRequest');
Yii::import('application.vendors.metatune.MBSimpleXMLElement');
Yii::import('application.vendors.metatune.SpotifyItem');
Yii::import('application.vendors.metatune.MetaTuneException');
....
class MetaTune {
const CACHE_DIR = 'application/vendors/metatune/cache/'; // Cache directory (must be writable) relative to this file
const USE_CACHE = false; // Should caching be activated?
const CACHE_PREFIX = "METATUNE_CACHE_"; // prefix for cache-files.
const SERVICE_BASE_URL_SEARCH = "http://ws.spotify.com/search/1/";
const SERVICE_BASE_URL_LOOKUP = "http://ws.spotify.com/lookup/1/";
const PLAYBUTTON_BASE_URL = "https://embed.spotify.com/?uri=";
public $autoAddTracksToPlayButton = false;
private $list = array();
// Holds instance
private static $instance;
.....
public static function getSomething()
{
if (!isset(self::$instance))
{
$class = __CLASS__;
self::$instance = new $class;
}
return self::$instance;
}
.....
public function searchTrack($name, $page = 1)
{
$url = self::SERVICE_BASE_URL_SEARCH . "track?q=" . $this->translateString($name) .
$this->addPageSuffix($page);
$contents = $this->requestContent($url);
$xml = new MBSimpleXMLElement($contents);
$tracks = array();
foreach ($xml->track as $track)
{
$tracks[] = $this->extractTrackInfo($track);
}
if ($this->autoAddTracksToPlayButton) {
$this->appendTracksToTrackList($tracks);
}
return $tracks;
}
If you have any suggestions I would be most grateful. Thanks.
You didn't initialize $spotify anywhere, and php made it into stdClass by default, since you were assigning values like to member properties using that variable, but it failed when you tried calling unexisting method on it.
Solution: initialise it before you use it
$spotify = MetaTune::getInstance();
I need to write the class in PHP. Input takes the path (directory name). The class has two methods:
files - returns an array of file names of this directory.
table - returns a generated html table with a list of files in this directory.
How do I do this?
You don't need to create a class for this. In fact, you should not. That is overly complex and entirely unnecessary.
If you need to read the list of files in a directory, you have three options: readdir, glob, or DirectoryIterator.
If you need to read the list of files in a directory, and all the directories inside of it, then you want to use RecursiveDirectoryIterator.
There are adequate usage examples on the linked documentation pages.
Using these, you can get your list'o'files and build your HTML.
I think it is good to create a class for such functionaliteit, because you can much better predict its behaviour and work around subtle changes in PHP over different versions. Also, you can create different classes to read lists of files from other locations like a database or csv file.
In this case, I extended a renderer class from the base class, because I figured the rendering shouldn't be part of the base class. In fact, it might be better to create a separate class for this that uses any descendant of Folder to render it. But I'll leave it to you to figure out what suits you best.
<?
class Folder
{
private $folder = '';
public function getFolder()
{
return $this->folder;
}
protected function setFolder($value)
{
$this->folder = (string)$folder;
}
public __construct($folder)
{
this->setFolder($folder);
}
public function readFileNames()
{
$folder = (string)$this->getFolder();
if ($folder === '')
{
throw new exception("Folder name is empty");
}
if (is_dir($folder) !== true)
{
throw new exception("'$folder' is not a directory.");
}
$dir = #opendir($this->folder);
if ($dir === false)
{
throw new exception("Cannot open directory '$folder'.");
}
$result = array();
while (false !== ($fileName = readdir($dir)))
{
if (is_file($fileName) === true)
{
$result[] = $fileName;
}
}
return $result;
}
public function readFiles()
{
$fileNames = $this->readFileNames();
$fileNames = array_flip($fileNames);
foreach($fileNames as $fileName=>&$fileContents)
{
if (false === ($file = #readFile($fileName)))
{
$fileContents = null;
}
else
{
$fileContents = $file;
}
}
}
}
class FolderTableRenderer extends Folder
{
public function renderTable()
{
?>
<table>
<thead><tr><th>File name</th></tr></thead>
<tbody>
<?
foreach ($this->readFileNames() as $fileName)
{
?>
<tr><td><?=$fileName?></td></tr>
<?
}
?>
</tbody>
</table>
<?
}
}
Very simple example of class.
class MyFiles {
public static function files($path) {
// Logic used to get the files found at path and return an array
// Just use the built-in functionality of PHP
$filesArray = array();
if (!is_dir($path)) {
return $filesArray;
}
$dir = opendir($path);
while (false !== ($filename = readdir($dir))) {
if (!is_dir($filename)) {
$filesArray[] = $filename;
}
}
return $filesArray;
}
public static function table($path) {
$files = self::files($path);
$c_files = count($files);
if ($c_files == 0) {
return "<table><tbody><tr><td>No files at $path</td></tr></tbody></table>";
}
$table = "";
for ($i = 0; $i < $c_files; $i++) {
$table .= "<tr><td>{$files[$i]}</td></tr>";
}
return "<table><tbody>$table</tbody></table>";
}
}
$fileTable = MyFiles::table('/my/path/with/files');