Ankündigung

Einklappen
Keine Ankündigung bisher.

Laravel/Eloquent Relations

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Laravel/Eloquent Relations

    Hallo,
    ich arbeite gerade mit Eloquent von Laravel und bekomme grade meine Datenbankstruktur nicht so abgebildet, wie ich es gerne hätte.

    Folgende Tabellenstruktur besteht bereits:
    Code:
    profile_field
    	id (PK,AI)
    	name
    	description
    
    user
    	id (PK,AI)
    	role_id (FK)
    	email
    	password
    	
    user_profile
    	user_id (PK,FK)
    	profile_field_id (PK,FK)
    	value
    
    role
    	id (PK,AI)
    	name
    	
    role_profile_field
    	role_id (PK,FK)
    	profile_field_id (PK,FK)
    	
    PK=Primary Key
    FK=Foreign Key
    AI=Auto Increment
    Im späteren System sollen bei einem Nutzer nur die Profileinträge angezeigt werden, die über role_profile_field für eine Rolle definiert wurden. Die dazugehörigen Werte werden in user_profile gespeichert. Dabei möchte ich über User bspw. auf das Model UserProfile zugreifen (den Wert bekommen) und über UserProfile den dazugehörigen Namen aus profile_field erhalten.

    Ich habe mich mittlerweile in den letzten Stunden so verzettelt, dass ich auch den Überblick verloren habe in den paar Models.
    Wenn es gewünscht wird kann ich gerne meinen derzeitigen Stand noch posten.

    Welche Beziehungen muss ich in den Models zwischen den Tabellen definieren?

    Verstehe ich die Doku richtig, so muss ich eine BelongsToMany Beziehung definieren, wüsste dann aber nicht mehr wie ich die value in user_profile erreiche.

    Edit:
    Da ich mit Eloquent noch am Anfang stehe (vom Wissensstand und vom Aufbau) und ich nur das aus Laravel nutze und dazu kommt, dass solche Konstrukte häufiger vorkommen werden, würdet ihr mir eher zu einem anderen ORM-Framework raten?
    Wichtig ist mir nach der einmaligen Definition ein einfaches Auslesen der Datenbank. Die Queries sollten dabei nicht exorbitant hoch sein. Daher fand ich das Eager-Loading interessant und wollte es mal Testweise in das Projekt einbauen.

    Edit2:
    Naja ich habe es jetzt so irgendwie hinbekommen, aber da es die erste Benutzung ist, würde ich dennoch gerne einmal ein Feedback bekommen:

    User.php
    PHP-Code:
    class User extends \Illuminate\Database\Eloquent\Model {
        protected 
    $table 'user';
        protected 
    $guarded = array('id');
        public function 
    role()
        {
            return 
    $this->belongsTo('\Model\Role');
        }
        public function 
    profileFields()
        {
            return 
    $this->belongsToMany('\Model\ProfileField','user_profile','user_id');
        }
        public function 
    userProfile()
        {
            return 
    $this->hasMany('\Model\UserProfile','user_id');
        }

    ProfileField.php
    PHP-Code:
    class ProfileField extends Model{
        protected 
    $table 'profile_field';
        protected 
    $guarded = array('id');
        public function 
    userProfile()
        {
            return 
    $this->belongsToMany('\Model\UserProfile','user_profile','profile_field_id');
        }

    UserProfile.php
    PHP-Code:
    class UserProfile extends Model{
        protected 
    $table 'user_profile';
        protected 
    $guarded = array('id');
        public function 
    user()
        {
            return 
    $this->belongsTo('\Model\User','user_id');
        }
        public function 
    profileField()
        {
            return 
    $this->belongsTo('\Model\ProfileField','profile_field_id');
        }

    Role.php
    PHP-Code:
    class Role extends Model{
        protected 
    $table 'role';
        protected 
    $guarded = array('id');
        public function 
    users()
        {
            return 
    $this->hasMany('\Model\User');
        }
        public function 
    roleProfileFields()
        {
            return 
    $this->belongsToMany('\Model\ProfileField','role_profile_field','role_id');
        }

    RoleProfile.php
    PHP-Code:
    class RoleProfile extends Model{
        protected 
    $table 'role_profile_field';
        public function 
    profileFields()
        {
            return 
    $this->belongsToMany('\Model\ProfileField','profile_field_id');
        }
        public function 
    roles()
        {
            return 
    $this->belongsToMany('\Model\Role','role_profile_field','');
        }

    Dieser Code
    PHP-Code:
    $users User::where('id',2)->with('userProfile','userProfile.profileField')->get();
    $arr $users->toArray();
    var_dump($arr); 
    ergibt dann folgende Ausgabe:
    Code:
    array(1) {
      [0]=>
      array(7) {
        ["id"]=>
        int(2)
        ["role_id"]=>
        int(6)
        ["regstamp"]=>
        int(0)
        ["email"]=>
        string(20) "geschwärzt"
        ["password"]=>
        string(32) "***"
        ["user_profile"]=>
        array(2) {
          [0]=>
          array(4) {
            ["user_id"]=>
            int(2)
            ["profile_field_id"]=>
            int(1)
            ["value"]=>
            string(5) "Hans"
            ["profile_field"]=>
            array(3) {
              ["id"]=>
              int(1)
              ["name"]=>
              string(7) "vorname"
              ["description"]=>
              string(0) ""
            }
          }
          [1]=>
          array(4) {
            ["user_id"]=>
            int(2)
            ["profile_field_id"]=>
            int(2)
            ["value"]=>
            string(8) "Meier"
            ["profile_field"]=>
            array(3) {
              ["id"]=>
              int(2)
              ["name"]=>
              string(8) "nachname"
              ["description"]=>
              string(0) ""
            }
          }
        }
      }
    }
    Ich hätte lieber mit dem Objekt weitergearbeitet, aber dann ist es sehr umständlich an die ganzen Werte zu kommen.
    Für jeden Kommentar bin ich dankbar

    Gruß
    Dreamwatcher
    War der Beitrag hilfreich? Dann Bedank dich mit einem klick auf .

  • #2
    Da ich mit Eloquent noch am Anfang stehe (vom Wissensstand und vom Aufbau) und ich nur das aus Laravel nutze und dazu kommt, dass solche Konstrukte häufiger vorkommen werden, würdet ihr mir eher zu einem anderen ORM-Framework raten?
    Nein - warum, aufgrund von Anfangsschwierigkeiten? Das wird schon werden. Im Endeffekt werden dir nur belongsTo und belongsToMany am häufigsten begegnen.
    Wichtig ist mir nach der einmaligen Definition ein einfaches Auslesen der Datenbank.
    Ist meiner Meinung nach gegeben.

    PHP-Code:
    User::where('id',2
    ist übrigens das gleiche wie
    PHP-Code:
     User::whereId(2
    Ansonsten schaut das doch nach einmal kurz überfliegen gut aus. Ich bin aber nicht der Ansicht, dass eager loading an der Stelle wirklich notwendig ist. Es hängt natürlich davon ab, was du da noch zu tun vorhast aber ob du einen Query hast oder drei - wie relevant ist das? eager loading wird wichtig, wenn man z. B. 100 User abfragt und dann bei allen auf Profilfelder zugreift und somit 201 Queries hätte statt nur eines einzigen.

    Was genau ist dein Problem mit Objekt statt Array?

    PS: Kennst du schon Ardent? https://github.com/laravelbook/ardent
    Es vereinfacht Eloquent ein wenig.

    Kommentar


    • #3
      Zitat von monolith Beitrag anzeigen
      Nein - warum, aufgrund von Anfangsschwierigkeiten? Das wird schon werden. Im Endeffekt werden dir nur belongsTo und belongsToMany am häufigsten begegnen.
      Ich weiß, ist ja jedesmal so. Hauptsache am Ende kann damit schnell gearbeitet werden.

      Zitat von monolith Beitrag anzeigen
      PHP-Code:
      User::where('id',2
      ist übrigens das gleiche wie
      PHP-Code:
       User::whereId(2
      Ah, okay. find(2) hat hierbei nicht gegriffen, weshalb ich das erstmal nur intuitiv genutzt hatte. Dann werde ich das noch ändern.

      Zitat von monolith Beitrag anzeigen
      Was genau ist dein Problem mit Objekt statt Array?
      Wenn ich mir die Collection anschaue, die ich erhalte, dann sieht mir das toArray nach einem Overhead aus, der nicht zwingend notwendig ist.
      Außerdem sind Objekte flexibler (im Sinne von weiteren Methoden, nicht von der Datenhaltung).
      Konvertiere ich es zu einem Array, dann ist für eine bessere Nutzung (ohne ständig prüfen zu müssen ob dieses oder jenes im Array vorhanden ist) erforderlich einen EntityMapper zu implementieren (oder?).


      Zitat von monolith Beitrag anzeigen
      PS: Kennst du schon Ardent? https://github.com/laravelbook/ardent
      Es vereinfacht Eloquent ein wenig.
      Werde ich mir mal anschauen. Danke.

      Gibt es Möglichkeiten, die von mir benötigten Beziehungen immer zu laden ohne, dass ich es bei dem Query angeben muss? Ich bin kein Fan davon, wenn es möglich ist, dass ähnliche Abfragen unterschiedliche Ergebnisse zurückliefern.
      Wenn zB. die Funktion getAllUsers() den Benutzer und seine Profilfelder zurückgibt und getUsersByRoleId($id) nur die Benutzer ohne weitere Beziehungen.
      War der Beitrag hilfreich? Dann Bedank dich mit einem klick auf .

      Kommentar


      • #4
        Du kannst dir einfach so eine Methode als Scope bauen und dann machen:
        PHP-Code:
        $users User::allUsers()->get() 
        Schau mal in der Doku im Eloquent-Kapitel nach query scopes: http://laravel.com/docs/eloquent#query-scopes

        Kommentar


        • #5
          Danke, das hätte ich eigentlich auch sehen müssen, steht es doch nur ein Abschnitt über dem, den ich postete.
          Der Punkt ist eben wichtig, weil an dem Projekt auch unerfahrenere Entwickler arbeiten und ich keine Lust auf Überraschungen habe
          War der Beitrag hilfreich? Dann Bedank dich mit einem klick auf .

          Kommentar

          Lädt...
          X