Call to undefined relationship in Eloquent, Laravel 5.7 - postgresql

I am four hours in this. I just cannot see the problem. I using Postgres not Mysql.
class ValorVariacao
public $table = 'valores_variacoes';
protected function tipoVariacao()
{
return $this->belongsTo('App\TipoVariacao', 'tipo_atributo_id', 'id');
}
The other class of the relationship.
class TipoVariacao
public $table = 'tipos_variacoes';
public function valorVariacao() {
return $this->hasMany('App\ValorVariacao', 'id', 'tipo_atributo_id');
}
The relevant structure of the table
valores_variacoes tipos_variacoes
id id
tipo_atributo_id
Calling this I get undefined relationship:
return ValorVariacao::with('tipoVariacao')->get();
error:
Call to undefined relationship [tipoVariacao] on model [App\ValorVariacao].

The relationship method has to be public:
public function tipoVariacao()
{
return $this->belongsTo('App\TipoVariacao', 'tipo_atributo_id', 'id');
}

Related

eloquent go to the wrong table just on store method

i have a problem that make my head blow about eloquent went to the wrong table here my code for my activity model
class Activity extends Model{
use HasFactory;
protected $table = 'activities';
protected $guarded = ['id'];
public function getRouteKeyName()
{
return 'slug';
}
and the problem is when i store to the database, eloquent went to the wrong table
here is my store method
public function store(StoreActivityRequest $request)
{
$validatedData = $request->validate([
'name' => 'required',
'slug' => 'required|unique:activies'
]);
Activity::create($validatedData);
return redirect('/activities')->with('success', 'Tindakan Berhasil Ditambahkan');
}
this is my customrequest (actually my laravel make it by default)
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class StoreActivityRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
];
}
}
here is the message
Illuminate\Database\QueryException
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'klinik_app.activies' doesn't exist (SQL: select count(*) as aggregate from `activies` where `slug` = konsultasi)
its go to activies table... if i change the tables on migrate file to activies, then the other method gone wrong because it's can't found activities. and this problem just happen to my store method, another method just do the right thing... is there any body can help me?
Update: Added from comments:
public function store(StoreActivityRequest $request) {
$validatedData = $request->validate([
'name' => 'required',
'slug' => 'required|unique:activies'
]);
Activity::create($validatedData);
return redirect('/activities')->with('success', 'Tindakan Berhasil Ditambahkan');
}

Get distinct emails of users who commented on a ticket in Laravel

I have the following models.
Ticket
class Ticket extends Model
{
protected $fillable = ['title', 'content', 'slug', 'status', 'user_id'];
protected $guarded = ['id'];
public function user()
{
return $this->belongsTo('App\User', 'user_id');
}
public function comments()
{
return $this->hasMany('App\Comment', 'post_id', 'id');
}
public function commenters()
{
return $this->hasManyThrough('App\User', 'App\Comment');
}
}
Comment
class Comment extends Model
{
protected $guarded = ['id'];
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function ticket()
{
return $this->belongsTo('App\Ticket', 'post_id', 'id');
}
public function post()
{
return $this->morphTo();
}
}
User
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
protected $guarded = ['id'];
protected $hidden = [
'password', 'remember_token',
];
}
A ticket has many comments
A comment has one user
I'm trying to extract a name-string list of users who commented on a ticket, but with no success.
In my controller, I'm using the following code to extract the list of commenters.
Ticket::where('id', $comment->post_id)->commenters
However, I'm getting the error:
Property [commenters] does not exist on the Eloquent builder instance.
You're missing a closure. This query is unfinished:
Ticket::where('id', $comment->post_id)
And an unfinished query is an instance of the Builder class, not a Ticket instance, or Collection of Ticket instances as you're expecting.
If you're expecting a single Ticket instance, then you'd use ->first():
$ticket = Ticket::where('id', $comment->post_id)->with(['commenters'])->first();
$commenters = $ticket->commenters;
If you're expecting multiple Ticket instances, then you'd use ->get():
$tickets = Ticket::where('id', $comment->post_id)->with(['commenters'])->get();
foreach($tickets AS $ticket){
$commenters = $ticket->commenters;
}
Note: ->with(['commenters']) is used to speed up the loading of ->commenters; if you omit it, then a new query is run when you try to access $ticket->commenters.

Laravel 5 Eloquent Relationship - Has Many Though

I have three models.
Study
Site
Unit
Study Has and belongs to many Sites and each site that belongs to Study again has and belongs to many Unit. Please see the following drawing.
http://tinypic.com/r/ojhx0g/8
How I achieve this using Laravel 5 Eloquent Relationships.
It sounds like you have many-to-many relationships between Study->Site and Site->Unit. You can read the Laravel documentation about many-to-many relationships here.
Models
Here are the relevant functions you'll need for Eloquent to recognize the relationships.
class Study extends Model {
// If you named your table differently (like 'studies'), specify that here
protected $table = 'studys';
// This assumes a pivot table named 'site_study', if you named yours
// differently you can pass in into the belongsToMany() function as the
// second parameter.
public function sites() {
return $this->belongsToMany('App\Site');
}
}
class Site extends Model {
protected $table = 'sites';
public function studies() {
return $this->belongsToMany('App\Study');
}
public function units() {
return $this->belongsToMany('App\Unit');
}
}
class Unit extends Model {
protected $table = 'units';
public function sites() {
return $this->belongsToMany('App\Site');
}
}
Then, to access the Sites belonging to a Study you would do this:
$sites = Study::find(1)->sites;
Pivot Table Migrations
Laravel expects pivot tables to be named like 'alpha_beta' where alpha and beta are the singular model names in alphabetical order. So your migrations for the pivot tables would look like this:
class CreateSiteStudyTable extends Migration {
public function up() {
Schema::create('site_study', function(Blueprint $table)) {
$table->integer('site_id')->unsigned();
$table->foreign('site_id')->references('id')->on('sites');
$table->integer('study_id')->unsigned();
$table->foreign('study_id')->references('id')->on('studys'); // or whatever you named it
$table->unique(['site_id', 'study_id']);
$table->timestamps();
});
}
public function down() {
Schema::drop('site_study');
}
}
class CreateSiteUnitTable extends Migration {
public function up() {
Schema::create('site_unit', function(Blueprint $table)) {
$table->integer('site_id')->unsigned();
$table->foreign('site_id')->references('id')->on('sites');
$table->integer('unit_id')->unsigned();
$table->foreign('unit_id')->references('id')->on('units');
$table->unique(['site_id', 'unit_id']);
$table->timestamps();
});
}
public function down() {
Schema::drop('site_unit');
}
}
You can read about Foreign Keys in Laravel here.
you have to create 3 models study, site and unit as per you diagram study has many sites and sites has many units, in you diagram study don't have direct relation with units your eloquent models will be like this.
class Study extends Model {
public function sites(){
return $this->hasMany('App\Site');
}
}
class Site extends Model {
public function units(){
return $this->hasMany('App\Unit');
}
public function study(){
return $this->belongsTo('App\Study');
}
}
class Unit extends Model {
public function sites(){
return $this->belongsTo('App\Site');
}
}

How to create generic EF Insert method?

I'd like to create a generic C# class with a method that will add a row to a database using Entity Framework.
I have one table called Address. I've written the following code to add an address to the database:
public class AddressExchange
{
public int Insert(Address address)
{
using (var db = new DemoWebEntities())
{
//db.AddObject("Address", address);
db.Addresses.AddObject(address);
db.SaveChanges();
return address.Id;
}
}
}
I would like to write a generic class that will perform this operation for any entity in my EDMX. I think that it should look something like this:
public class EntityExchange<T, KeyType>
{
public KeyType Insert(T t)
{
using (var db = new DemoWebEntities())
{
// The entity set name might be wrong.
db.AddObject(typeof(T).Name, t);
// EF doesn't know what the primary key is.
return t.Id;
}
}
}
I think it may be possible to use the AddObject method to add the object to the database, but the entityset name is not necessarily the same as the type name, especially if it has been pluralized!
I also want to return the primary key to the caller, but I don't know how to tell which field contains the primary key.
I have a generic InsertOrUpdate method in a generic repository that also ensures proxies are created. (Proxies are required to support lazy loading and if you create an entity using "new", then proxies are not created). See the question here
public class RepositoryBase<T> : IRepository<T> where T : ModelBase
{
public virtual T InsertOrUpdate(T e)
{
DbSet<T> dbSet = context.Set<T>();
//Generate a proxy type to support lazy loading
T instance = dbSet.Create();
DbEntityEntry<T> entry;
if (e.GetType().Equals(instance.GetType()))
{
//The entity being added is already a proxy type that
//supports lazy loading just get the context entry
entry = context.Entry(e);
}
else
{
//The entity being added has been created using the "new" operator.
//Attach the proxy
//Need to set the ID before attaching or we get
//The property 'ID' is part of the object's key
//information and cannot be modified when we call SetValues
instance.ID = e.ID;
entry = context.Entry(instance);
dbSet.Attach(instance);
//and set it's values to those of the entity
entry.CurrentValues.SetValues(e);
e = instance;
}
entry.State = e.ID == default(int) ?
EntityState.Added :
EntityState.Modified;
return e;
}
}
public abstract class ModelBase
{
public int ID { get; set; }
}
Note that all the models inherit ModelBase so that handles the ID issue and I return the entity rather than just the ID. That is probably not strictly necessary since a reference to the entity is passed in and EF performs fixup on the ID anyway so you can always access it from the refernce passed in.
This might be reliant on a particular version on Entity framework however this is how I do it
public void Create(T entity)
{
using (var db = new DemoWebEntities())
{
db.Set<T>().Add(entity);
}
}
For the primary key issue, can you use partial classes to make your entities implement an interface, something like this:
public interface IEntity
{
Guid PrimaryKey { get; }
}
Your entity classes would then return the appropriate value:
public partial class EntityType : IEntity
{
public Guid PrimaryKey
{
get
{
return this.WhateverId; // Return the primary key
}
}
}
Then, constrain your method to only accept IEntity:
public class EntityExchange<T, KeyType> where T : IEntity
And finally return the primary key after the insert:
return t.PrimaryKey;
May be it can help you.
public T Add(T model)
{
using (BigConceptEntities entity = new BigConceptEntities())
{
entity.Set<T>().Add(model);
entity.SaveChanges();
return model;
}
}

Zend DB Table and Model one to one

I have class that representing model of user with foreign key with is id of picture .
class Model_User extends Model_AbstractEntity
{
protected $u_id;
protected $u_email;
protected $u_firstname;
protected $u_lastname;
protected $u_password;
protected $u_salt;
protected $u_created_at;
protected $u_updated_at;
protected $u_fb;
protected $u_status;
protected $u_r_id;
protected $u_p_id;
}
Class with is responsible for picture model look like this:
class Model_Picture extends Model_AbstractEntity
{
protected $p_id;
protected $p_created_at;
protected $p_updated_at;
protected $p_caption;
protected $p_name;
protected $p_basePath;
protected $p_available;
protected $p_u_id;
}
This is only model part with is getting data from database.
Foreing key is u_p_id and key in picture is p_id
My problem is that when doing select() by Zend db table it returning me data with foreign key but how can I know which part of return data is picture part to set the proper picture model.... how to do it in proper way no to do 2 queries one for user and second for picture to create 2 associative objects.
I'm talking now about relation ont to one but maybe will be one to many..
Typically your entity models will not exist in void they will exist in concert with some type of Data Mapper Model. The Mapper will typically be charged with gathering the data from whatever source is handy and then constructing the entity model.
For example I have a music collection that has an album entity:
<?php
class Music_Model_Album extends Model_Entity_Abstract implements Interface_Album
{
//id is supplied by Entity_Abstract
protected $name;
protected $art;
protected $year;
protected $artist; //alias of artist_id in Database Table, foreign key
protected $artistMapper = null;
/**
* Constructor, copied from Entity_Abstract
*/
//constructor is called in mapper to instantiate this model
public function __construct(array $options = null)
{
if (is_array($options)) {
$this->setOptions($options);
}
}
/**
* Truncated for brevity.
* Doc blocks and normal getters and setters removed
*/
public function getArtist() {
//if $this->artist is set return
if (!is_null($this->artist) && $this->artist instanceof Music_Model_Artist) {
return $this->artist;
} else {
//set artist mapper if needed
if (!$this->artistMapper) {
$this->artistMapper = new Music_Model_Mapper_Artist();
}
//query the mapper for the artist table and get the artist entity model
return $this->artistMapper->findById($this->getReferenceId('artist'));
}
}
//set the artist id in the identity map
public function setArtist($artist) {
//artist id is sent to identity map. Can be called later if needed - lazy load
$this->setReferenceId('artist', $artist);
return $this;
}
//each album will have multiple tracks, this method allows retrieval as required.
public function getTracks() {
//query mapper for music track table to get tracks from this album
$mapper = new Music_Model_Mapper_Track();
$tracks = $mapper->findByColumn('album_id', $this->id, 'track ASC');
return $tracks;
}
}
In the mapper I would build the entity model like:
//excerpt from Model_Mapper_Album
//createEntity() is declared abstract in Model_Mapper_Abstract
public function createEntity($row)
{
$data = array(
'id' => $row->id,
'name' => $row->name,
'art' => $row->art,
'year' => $row->year,
'artist' => $row->artist_id,//
);
return new Music_Model_Album($data);
}
to use this method in a mapper method, might look like:
//this is actually from Model_Mapper_Abstract, b ut give the correct idea and will work in any of my mappers.
//this returns one and only one entity
public function findById($id)
{
//if entity id exists in the identity map
if ($this->getMap($id)) {
return $this->getMap($id);
}
//create select object
$select = $this->getGateway()->select();
$select->where('id = ?', $id);
//fetch the data
$row = $this->getGateway()->fetchRow($select);
//create the entity object
$entity = $this->createEntity($row);
//put it in the map, just in case we need it again
$this->setMap($row->id, $entity);
// return the entity
return $entity;
}
I have seen Entities and Mappers built in many different ways, find the method that you like and have fun.
A lot of code has been left out of this demonstration as it doesn't really apply to the question. If you need to see the complete code see it at GitHub.