Laravel Eloquent, return JSON with "belongsTo" object? - orm

I have two models with a one-to-many relationship.
class User extends ConfideUser {
public function shouts()
{
return $this->hasMany('Shout');
}
}
class Shout extends Eloquent {
public function users()
{
return $this->belongsTo('User');
}
}
This seem to work fine.
BUT, How do I get this to return the users object nested in the shout objects?
Right now it only returns all my Shouts, but I have no access in the JSON to the belonging user model.
Route::get('api/shout', function() {
return Shout::with('users')->get();
});
This just returns this JSON, with no user object for every shout:
[{"id":"1","user_id":"1","message":"A little test shout!","location":"K","created_at":"2013-05-23 19:51:44","updated_at":"2013-05-23 19:51:44"},{"id":"2","user_id":"1","message":"And here is an other shout that is a little bit longer...","location":"S","created_at":"2013-05-23 19:51:44","updated_at":"2013-05-23 19:51:44"}]

I was having the same trouble using Laravel 5. Just wanted to add that I got it to work by using the Model::with("relationship")->get() method on the model.

I figured it out.
The method needs to be named user() not users() when working with "belongsTo" relationship.
Makes sense.
And seems to work.

If you are using:
protected $visible = ['user'];
Don't forget to add there relationship, to be visible in JSON

u can use protected $with = ['users']; on Class Shout and use protected $with = ['shouts'];.
and Give Full namespace model name
class Shout extends Eloquent {
protected $with = ['users'];
public function users()
{
return $this->belongsTo('App\User');
}
}
and
class User extends ConfideUser {
protected $with = ['shouts'];
public function shouts()
{
return $this->hasMany('App\Shout');
}
}
Receive It
Route::get('api/shout', function() {
return Shout::all()->toJson;
});

Related

Call to a member function addEagerConstraints() on null laravel8

i want fetch two tables data using with() but getting error as "Call to a member function addEagerConstraints() on null "
I have author model with multiple post relationship
My model relation as follows as follows:
Post relationship :
class Post extends Model
{
use HasFactory;
public function author(){
$this->belongsTo(Author::class);
}
}
Author model as follows:
class Author extends Model
{
use HasFactory;
public function post(){
return $this->hasMany(Post::class);
}
}
my migration of post table as follows:
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('cat');
$table->timestamps();
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('authors');
});
I am trying to fetch data in controller as follows using with() in postcontroller
public function index(){
return $data = Post::with('author')->get();
}
But getting error as Call to a member function addEagerConstraints() on null . Anyone have idea what is wrong in that then please let me know.
Can you try adding a return statement;
class Post extends Model
{
use HasFactory;
public function author(){
return $this->belongsTo(Author::class);
}
}

override relation in Laravel

I am working on limiting access depending on user roles.
I want to be able to somehow override a belongsToMany relation to return all, if user->isAdmin() returns true.
Currently have as the AccountController index method:
public function index()
{
if(Auth::user()->isAdmin()) // can this go in beforeFilter?
return Account::all();
else
return Auth::user()->accounts;
}
in my User model:
public function accounts()
{
return $this->belongsToMany("Account");
}
Is there a neat way to do this without needing an if statement in the controller functions?
You cannot do this.
The relation method must return an instance of Relation, otherwise it throws an error.
There's nothing stopping you from creating a separate method for this:
AccountController.php:
public function index()
{
return Auth::user()->userAccounts();
}
User.php:
public function accounts()
{
return $this->belongsToMany("Account");
}
public function userAccounts()
{
if ($this->isAdmin()) return Account::all();
return $this->accounts;
}

Laravel relational delete between three models

I have a simple relational models that I've built like that :
Parent :
<?php
class Appartement extends Eloquent {
public function gallery()
{
return $this->hasOne('Gallery', 'object_id')->where('type', '=', 'appartement');
}
public function delete()
{
$this->gallery()->delete();
return parent::delete();
}
}
First children Gallery
class Gallery extends \Eloquent {
protected $fillable = [];
public function images()
{
return $this->hasMany('GalleryImage');
}
public function delete()
{
$this->images()->delete();
return parent::delete();
}
}
Second Children Images
class GalleryImage extends \Eloquent {
protected $fillable = [];
public function gallery()
{
return $this->belongsTo('Gallery');
}
public function delete()
{
unlink(public_path().$this->link);
return parent::delete();
}
}
So basically nothing big : One appartement has one gallery, one gallery has many images.
It works pretty well, the problem is that when I delete an appartement, I would like to delete the gallery and the images associated to the appartement.
So I've tried to override the delete method.
Appartement get deleted, as well as gallery, but the images are not deleted, and it seems that there is no access to the delete function of Gallery, because I've tried to add a die; in the function, but it never dies.
Does anyone know how I can overcome this ?
Thanks
You have 2 options, the first is to set up foreign key constraints and cascade on delete using your migrations
// gallery migration
DB::table('galleries', function($table){
$table->foreign('object_id')
->references('id')->on('appartments')
->onDelete('cascade');
});
// images migration
DB::table('images', function($table){
$table->foreign('gallery_id')
->references('id')->on('galleries')
->onDelete('cascade');
});
The other option is to use model observers
here is an example: http://www.laravel-tricks.com/tricks/cascading-deletes-with-model-events this is useful on DB's that don't support FK constraints.

Creating queries in Paris ORM

I have a collection of Recipes and each one contains Categories. This are my models:
class Recipe extends \Model {
public static $_table = "recipe";
public function categories() {
return $this->has_many_through('Category');
}
}
class Category extends \Model {
public static $_table = "category";
public function categories() {
return $this->has_many_through('Recipe');
}
}
And the table to relate both:
class CategoryRecipe extends \Model {
public static $_table = "category_recipe";
}
Now I need to create a query to get all the Recipes that are under one/more categories. What is the way to achieve this? I want to avoid making things like this:
$results = $app['paris']->getModel('CategoryRecipe')
->where_in("category_id",$selected_categories)
->find_many();
foreach($results as $result) {
$recipe = $app['paris']->getModel('Recipe')
->where('id',$result->recipe_id)
->find_one();
var_dump($receta->name);
}
Create filters? functions inside the models? Is not possible to make it more elegant?
That is pretty much how I would do it, but you can optimise in one way. Add relation functions to your linking/many-to-many table. Then instead of doing that extra query in your foreach loop you simply do:
foreach($results as $result) {
$recipe = $result->recipe()->find_one();
var_dump($recipe)
}
So your CategoryRecipe model might look like:
class CategoryRecipe extends \Model {
public static $_table = "category_recipe";
public function recipe() {
$this->belongs_to('Recipe', 'recipe_id');
}
public function category() {
$this->belongs_to('Category', 'category_id');
}
}
I haven't tested this code, but it should be what you're after I think.

User scope with Zend Framework

I'm switching a Zend Framework application from mono-user to multi-user.
What is the best approach to include the user scope in the controllers ?
One way would be to add the user id in each methods in every controllers:
/application/controllers/IndexController.php
...
public function indexAction() {
$params['user_id'] = Zend_Auth::getInstance()->getIdentity()->id;
$listHelper->readItems($params);
}
...
An other one would be to create a new User model and fetch his items :
/application/controllers/IndexController.php
...
public function indexAction() {
$userModel = new application_models_user();
$userModel->find(Zend_Auth::getInstance()->getIdentity()->id);
$userModel->readItems();
}
...
I'm wondering what's the best approach that would allow me to write minimal code and if you have another idea to "automagically" add the user scope (db scope, plugin...).
Create an abstract class by extending Zend_Controller_Action
abstract class My_Controller_Action extends Zend_Controller_Action {
private $userModel;
public function getUserModel() {
if(is_null($this->userModel)) $this->userModel = new application_models_user();
return $this->userModel;
}
public function getUserId() {
return $this->getUserModel()->find(Zend_Auth::getInstance()->getIdentity()->id);
}
}
Now use this class as base class for your controllers.