Symfony 4, erhalten Sie den Stammpfad des Projekts von einer benutzerdefinierten Klasse (keine Controller-Klasse)

Lesezeit: 4 Minuten

Im Verzeichnis src/Utils habe ich eine benutzerdefinierte Klasse erstellt Foo für verschiedene Dinge. Ich suche nach einer Möglichkeit, den absoluten Root-Pfad des Symfony 4-Projekts zu erhalten

Von einem Controller aus ist es einfach mit:

$webPath = $this->get('kernel')->getProjectDir();

Aber wie kann ich aus einer benutzerdefinierten Klasse, die ich in meinem src/Utils-Verzeichnis erstellt habe, das Stammpfadverzeichnis abrufen?

Ich könnte den Pfad vom Controller an den übergeben Foo Klasse :

$webPath = $this->get('kernel')->getProjectDir();
$faa = new Foo($webPath);
$faa->doSomething();

aber ich denke, es ist richtiger, diese Informationen in der Foo-Klasse zu speichern und nur “Controller-Logik” in der Controller-Klasse zu haben

  • Übergeben Sie diesen Wert als Parameter an die Foo-Klasse Konstrukteur die automatisch verdrahtet werden.

    – u_mulder

    17. Oktober 2018 um 8:33 Uhr


  • Hmmm, ist es möglich, mir ein Beispiel mit der Konstruktmethode zu geben?

    – Leerzeichen

    17. Oktober 2018 um 8:43 Uhr

Benutzer-Avatar
Tomasz

Bei Symfony AppKernel Die Klasse behandelt das Projektstammverzeichnis unter der Methode getProjectDir(). Um es in den Controller zu bekommen, können Sie Folgendes tun:

$projectRoot = $this->get('kernel')->getProjectDir();

Es gibt Ihnen ein Projektstammverzeichnis zurück.

Wenn Sie das Projektstammverzeichnis in einer Ihrer Klassen benötigen, haben Sie zwei Möglichkeiten, die ich Ihnen vorstellen werde. Zuerst geht vorbei AppKernel als Abhängigkeit:

class Foo 
{
    /** KernelInterface $appKernel */
    private $appKernel;

    public function __construct(KernelInterface $appKernel)
    {
        $this->appKernel = $appKernel;
    }
}

Dank der Autowiring-Abhängigkeiten von Symfony 4 wird es automatisch in Ihre Klasse eingefügt und Sie können darauf zugreifen, indem Sie Folgendes tun:

$this->appKernel->getProjectDir();

Aber bitte beachten Sie: Ich denke nicht, dass es eine gute Idee ist, bis Sie wirklich brauchen und mehr damit zu tun haben AppKernel Klasse, als das Projektstammverzeichnis abzurufen. Vor allem, wenn Sie später daran denken, Unit-Tests für Ihre Klasse zu erstellen. Sie würden automatisch die Komplexität erhöhen, wenn Sie Mock of erstellen müssten AppKernel zum Beispiel.

Zweite Option und IMHO besser wäre, nur eine Zeichenfolge mit dem Pfad zum Verzeichnis zu übergeben. Sie könnten dies erreichen, indem Sie einen Dienst darin definieren config/services.yaml so was:

services:
    (...)
    MyNamespace\Foo:
        arguments:
            - %kernel.project_dir%

und Ihr Konstruktor würde wie folgt aussehen:

class Foo 
{
    /** string $rootPath */
    private $rootPath;

    public function __construct(string $rootPath)
    {
        $this->rootPath = $rootPath;
    }
}

  • Für die allererste Erklärung sollten Sie auch erwähnen, dass sie enthalten sind use Symfony\Component\HttpKernel\KernelInterface; über der Klassendatei.

    – Kyeno

    15. Oktober 2020 um 7:40 Uhr

  • config/services.yaml and $rootPath sind gute Idee statt KernelInterface

    – Selim Resa

    17. Juni um 9:10 Uhr

Benutzer-Avatar
Artem

Ohne Kernel Injektion

config/services.yaml

services:
    _defaults:
        autowire: true
        autoconfigure: true
        bind:
            $projectDir: '%kernel.project_dir%'

….

class Foo
{
    private $projectDir;

    public function __construct(string $projectDir)
    {
        $this->projectDir = $projectDir;
    }
}

Benutzer-Avatar
f_i

Wenn Ihre Klasse erweitert wird:
Symfony\Bundle\FrameworkBundle\Controller\AbstractControllerdann können Sie das Stammverzeichnis als erhalten

$projectRoot = $this->getParameter('kernel.project_dir');

oder

Injizieren ContainerBagInterface zu Ihrem Controller

protected $projectRoot;

public function __construct(ContainerBagInterface $containerBag)
{
    $this->projectRoot = $containerBag->get('kernel.project_dir');;
}

oder

Noch besser und die empfohlene Vorgehensweise

Injizieren Sie die root_dir zu deinem Foo Klasse. Fügen Sie Ihrer Konfiguration unter Dienste Folgendes hinzu

services:
    foo:
        class:     App\Path\To\Foo
        arguments: ['%kernel.project_dir%']

Der Container sollte das Argument beim Auflösen an Ihre Klasse weitergeben, the Foo Klasse sollte so aussehen

<?php

namespace App\Path\To;

class Foo {

  private $projectDir;

  public function __construct($projectDir) 
  {
     $this->projectDir = $projectDir;
  }
}

  • In 2019/2020/2021, mit aktuellen Versionen von Symfony (4,5+) ist dies der Weg, dies zu tun.

    – gucken

    7. Dezember 2020 um 18:57 Uhr

  • Das letzte Beispiel hat bei mir super funktioniert. Allerdings musste ich umsteigen %kernel.root_dir% zu %kernel.project_dir%.

    – Nathanael

    22. Januar 2021 um 18:52 Uhr

Das ist Arbeit:

// from Foo class
use Symfony\Component\HttpKernel\KernelInterface;
...
class Foo{
    private $rootDir;
    public function __construct(KernelInterface $kernel)
    {
        $this->rootDir = $kernel->getProjectDir();
    }
    public function myfoomethod(){
        return $this->getRootDir();
    }
    public function getRootDir(){
        return $this->rootDir;
    }
}


// from the controller class 
use App\Utils\Foo;
...
class FaaController extends AbstractController
{
    /**
     * @Route("/scenario", name="scenario")
     */
    public function new(Foo $foo)
    {
        dump($foo->myfoomethod()); //show the dir path !
        return $this->render('faa/index.html.twig');
    }
}

Benutzer-Avatar
Sofia Grillo

Der einfachste Weg, dies zu tun, ohne nutzlose Abhängigkeiten einzufügen, besteht darin, eine Hilfsmethode wie diese zu erstellen (in meinem Fall ist sie in src\Utils\Utils.php):

namespace App\Utils;

public static function getRootDir(): string
{
    return __DIR__ . '/../..';
}

Dann ruf doch einfach überall mit an

Utils::getRootDir()

Es funktioniert sowohl unter Windows als auch unter Linux, aber wenn Sie es vorziehen, können Sie die verwenden DIRECTORY_SEPARATOR konstant statt "https://stackoverflow.com/"


Außerdem ist es viel effizienter als die Kernel::getProjectDir() Methode, die a instanziiert ReflectionObject und führt dann eine Rekursion durch, bis der Ordner mit composer.json gefunden wird, mit mehreren Überprüfungen, die E/A beinhalten, wie z is_file(). Verwendung der __DIR__ costant ist viel besser, da sein Wert bereits im Arbeitsspeicher verfügbar ist, ohne dass auf die physische Festplatte zugegriffen werden muss.

  • das sind KEINE NUTZLOSEN Abhängigkeiten, das ist Portabilität.

    – Medünen

    4. August um 0:48

  • das sind KEINE NUTZLOSEN Abhängigkeiten, das ist Portabilität.

    – Medünen

    4. August um 0:48

1257970cookie-checkSymfony 4, erhalten Sie den Stammpfad des Projekts von einer benutzerdefinierten Klasse (keine Controller-Klasse)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy