Skip to content

Instantly share code, notes, and snippets.

@byStrange
Created October 12, 2024 06:03
Show Gist options
  • Save byStrange/08cbfbaf1189819547b6817c794035d1 to your computer and use it in GitHub Desktop.
Save byStrange/08cbfbaf1189819547b6817c794035d1 to your computer and use it in GitHub Desktop.
<?php
namespace backend\widgets;
use Yii;
use yii\base\Widget;
use yii\helpers\Url;
use ReflectionClass;
class ControllerNavigatorWidget extends Widget
{
public $controllerNamespace = 'backend\\controllers';
public function run()
{
$controllerDir = Yii::getAlias('@backend/controllers');
$controllers = $this->findControllers($controllerDir);
return $this->render('controller-navigator', [
'controllers' => $controllers
]);
}
protected function findControllers($directory)
{
$controllers = [];
foreach (glob($directory . '/*Controller.php') as $file) {
$controllerClass = $this->controllerNamespace . '\\' . basename($file, '.php');
if (class_exists($controllerClass)) {
$reflection = new ReflectionClass($controllerClass);
$actions = $this->getControllerActions($reflection);
$controllerName = $reflection->getShortName();
$controllerName = str_replace('Controller', '', $controllerName);
$controllers[$controllerName] = $actions;
}
}
return $controllers;
}
protected function getControllerActions(ReflectionClass $reflection)
{
$actions = [];
foreach ($reflection->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
if (strpos($method->name, 'action') === 0 && $method->name !== 'actions') {
$actionName = str_replace('action', '', $method->name);
$actionName = strtolower(preg_replace('/(?<!^)[A-Z]/', '-$0', $actionName)); // Converts camelCase to kebab-case
$actions[] = $actionName;
}
}
return $actions;
}
}
@byStrange
Copy link
Author

Save it under you widgets folder, for example in advanced template backend\widgets
or in basic app app\widgets.

and inside widgets folder, create views folder and create that view file controller-navigator.php
and u can customize your view to display the links.
Simple example

<?php

use yii\helpers\Html;
use yii\helpers\Url;

function toKebabCase($string)
{
  $spacedString = preg_replace('/([a-z])([A-Z])/', '$1 $2', $string);

  $kebabCase = strtolower(str_replace(' ', '-', $spacedString));

  return $kebabCase;
}

$exlcudedActions = ['update', 'delete', 'view', 'create'];

foreach ($controllers as $controller => $actions): ?>
  <ul>
    <?php foreach ($actions as $action): ?>
      <?php if (!in_array($action, $exlcudedActions)): ?>
        <li>
          <a href="<?= Url::to(["/" . toKebabCase($controller) . "/{$action}"]) ?>">
            <?= ucfirst($controller) ?>
            <?= $action === 'index' ? '' :  ': ' . ucfirst($action) ?>
          </a>
        <?php endif; ?>
      <?php endforeach; ?>
  </ul>
<?php endforeach; ?>

note that controller names should be converted to kebab case (this is how a controller id is made).
Now you can use ControllerNavigatorWidget anywhere in the project.

Example usage:

<?php

use backend\widgets\ControllerNavigatorWidget;

?>

<?= ControllerNavigatorWidget::widget() ?>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment