Let's say I have an "Contact" entity, and I have built with model, controller, views. All CRUD operation works.
Now I want to add addresses to the contact. There may be more than address for the same contact, but each address belongs only to one contact. Any CRUD operation about an address is nested to a contact.
I have built the model, and so far so good. I have populated the database by hand and I want to implement the addresses.index nested to the contacts.show.
The Addresses controller method should be something like this:
public function index($ContactId)
{
$addresses = Addresses::where("contact_id",$ContactId)->paginate(10);
return view('addresses.index',compact('addresses',"$ContactId"))
->with('i', (request()->input('page', 1) - 1) * 5);
}
Now I want to build the view, but I'm lost, because I can't find any useful example or tutorial (or they are for a very old version)
I nest addresses completely within users, contacts, leads, companies, etc. including the view directories, so users.address.index would be the view path, for example.
The routes to access addresses are also nested. If it's a simple project with only user's having addresses, the url would be '/users/1/addresses` to list their addresses. A controller method to list the address would typically look like:
class AddressController {
public function index(Request $request, User $user) {
return view('users.addresses.index', ['addresses' => $user->addresses]);
}
}
Resource routing makes this all easy, you only have two route file entries like so:
Route::resource('users', 'UserController');
Route::resource('users.addresses', 'AddressController');
If I have several models in an application that can have addresses, I make Address polymorphic and abstract out the above controller further.
https://laravel.com/docs/5.5/eloquent-relationships#polymorphic-relations
Related
I am a newbe in Laravel. The docs show how to use relationships like this:
One To Many (Inverse) / Belongs To
Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a hasMany relationship, define a relationship method on the child model which calls the belongsTo method:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo(Post::class);
}
}
Once the relationship has been defined, we can retrieve a comment's parent post by accessing the post "dynamic relationship property":
use App\Models\Comment;
$comment = Comment::find(1);
return $comment->post->title;
My question is: Where is this code? In a controller or in a view?
If you use MVC structure, you should understand that
Model is layer where you store your data
View is layer where you should only display your data
and Controller is layer where you can keep your logic.
If you have a lot of difficult logic or big application, you should better to use Services, as layer between Controllers And Models.
Receiving Comments from model and prepeare them should be in controller level. In view level you just define how to show them to user.
I hope it will help you to understand difference between logic layers.
you can access this relationship in controller or view like this-
suppose you want to make relation between product model and brand model:-
in product model:-
public function brand(){
return $this->belongsTo('App\Model\Brand','brand_id','id');
}
now you are able to see which product belongs to which brand without any query or using loop.
just do in controller:-
$product=Product::with('brand')->get();
here you get all the data...
and when you use it on **view **just do it:
{{$product->brand->brand_name}}
//brand name should the column name
I hope you understood...
Happy Learning!
I'm having a problem. I have tables that relate:
internal_clients->subsidiaries->departments->job_titles->users
I also have their respective models.
My doubt is:
How do I get all the data associated with users from the top of the tree (internal_clients)
?
I'm trying to follow the Laravel documentation using hasManyThrough.
However, in the documentation it explains only how to do it in a chain of three tables. They teach how to place an intermediate table (model) as the second parameter of the hasManyThrough method (BaseClasse::class, IntermediaryClass::class).
However, in my case that has several tables between users and internal_clients, how would I do this? What would be the intermediate table?
I would like to make a query that returns the user's internal_client, subsidiary, department and jobTitle (associated with users).
I'm trying to do it this way:
Model InternalClient
public function users()
{
return $this->hasManyThrough(User::class, InternalClient::class);
}
Controller UserController
public function allRelations($internalClientId)
{
$internalClient = InternalClient::find($internalClientId);
$users = $internalClient->users;
return response()->json($users, 201);
}
The InternalClient id arrives at the controller above.
When I access the route, the error below is returned:
In short: I would like to know if there is a way to get all the data (from all tables that are in this hierarchical tree) that are associated with the User.
I couldn't find an answer on the Stackoverflow PT-BR.
Thank you!
I'm in a dilemma to find some sort of logic to restrict user access to content within the same model.
For example, a supplier only can see products that they supply and the customer only can see a product which they buying. (note: Each product can have multiple supplier or customers. We call id a product node)
Now, I have the relationship set to a product belongs to many suppliers and a product belongs to multiple customers.
Currently I have the spatie roles and permissions in my site, which works great for 1 tenant (mainly our office(50-150 users)). It is not a problem if our office user can see details of multiple customers or products, but the problem starts when the customer logs in. I only want to show the product pricing or data that belonging to them. It is a big no no to see any other customer or supplier data.
I looked multi tenancy implementation, but I believe this wouldn't cover my need.
I apologise if I've overlooked something, but I try to keep the data as secured as possible.
Could you please shed some light on this dilemma and direct me to the correct path?
Many thanks for your input!
I'm assuming that all of the models you want to restrict have a relationship directly to the customer, so you can actually add a global scope that adds a default parameter to the query.
Take the following scope:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Support\Facades\Auth;
class CustomerOwnedScope implements Scope {
public function apply(Builder $builder, Model $model) {
if (Auth::guard('customer')->check()) {
$builder->where('customer_id', '=', Auth::guard('customer')->id);
}
}
public function extend(Builder $builder) {
$this->addWithoutCustomer($builder);
}
protected function addWithoutCustomer(Builder $builder) {
$builder->macro('withoutCustomer', function (Builder $builder) {
return $builder->withoutGlobalScope($this);
});
}
}
Any model that has this scope will automatically add the clause WHERE customer_id = ? where ? is the id of the currently authenticated customer, if one is authenticated. Assuming that you're using Laravel auth this would prevent you from having to do anything specific to achieve your goal.
It also adds the scope withoutCustomer() that would prevent the where clause from being added.
The simplest way to add this to a model that belongs to a customer would be to create yourself a trait (concern) like so:
<?php
namespace App\Concerns;
use App\Scopes\CustomerOwnedScope;
trait OwnedByCustomer {
public static function bootOwnedByCustomer() {
static::addGlobalScope(new CustomerOwnedScope);
}
public function customer() {
$this->belongsTo(Customer::class, 'customer_id');
}
}
This would add the customer relationship as well as add the scope to automatically query based on the current customer.
You can obviously modify this further to include other relationships, or you can add some more conditions to only apply for customers with a certain flag set, or not set (for internal users, etc).
This whole approach does assume that your internal admin users and your external customer users are using different auth guards (which would be the ideal approach in this situation).
I should add that the code above is taken from an article I wrote on the subject of multi-tenancy, specifically the part about dealing with tenants in a single database. If you would like, you can read it here: https://ollieread.com/articles/laravel-multi-tenancy-avoiding-over-engineering#single-database
I have 2 controllers and models:
User Controller & Model
Hero Controller & Model
Each user can have unlimited heroes - it means that the relationship between them is one to many.
In my UserController I created the following method:
/**
* Get the heroes of the user.
*/
public function heroes()
{
return $this->hasMany(Hero::Class);
}
while in my HeroController I created this method:
/**
* Get the user that owns the hero.
*/
public function user()
{
return $this->belongsTo(User::class)
}
Added this to my routes file:
Route::get('userHeroes', 'UserController#heroes');
and it returns this error:
{"error":{"message":"Method [hasMany] does not exist.","status_code":500}}
What could have gone wrong.. ?
The controller is just a delegate between the request and the return data - you tell it that you want something, it figures out what you want, and then it calls the appropriate places to get something to return.
The hasMany() and belongsTo() methods, on the other hand, are logic specifically related to the Hero and User models, on the other hand.
What you need is to move the heroes() method to your User model, because a user can have many heroes. Also need the user() method to your Hero model, because a hero belongs to a user.
Then you put an action call in a controller. Let's say, for instance, that you have a UserController which has an getHeroes() method. That might look like this:
public function getHeroes() {
$user = auth()->user();
$heroes = $user->heroes;
return $heroes;
}
And that will format it to JSON. Just an example.
But you might want to read a tutorial or two about this, since it's fairly basic stuff and it's good to get a good handle on early on. Please don't take that the wrong way - we're happy to help if you run into problems, I just think you might need a stronger foundation. The screencasts at Laracasts are highly recommended for this purpose.
it must be declared in models, not in controllers, hasMany() is a method in eloquent models.
hasMany and belongsTo methods are eloquent class methods.
And we inherit eloquent in our model so that we can use the eloquent methods functionality.
In order to use the relation, you have to define the relation method in respective model class and then you can call from controller.
Please refer the documentation Eloquent relationship documentation
Hope i have cleared your doubt.
Thanks
Im at a bit of a loss. I have an api that will create a user upon a request. This is done no problem.
I also want to create another controller action or add to my current action the ability to create an address for the same user.
Is there an easy way to do this? Or should I stick to the
$user = new User(Input::all());
$user->save();
$address = new Address(Input::all());
$address->save();
You should set up relationships between your User and Address model - http://laravel.com/docs/eloquent#relationships and use associate/sync() to connect the dots.
This is a relationship problem. An address to a user will most likely be One-to-One (i.e., each Userhas a unique Address). A User might have an Address, but an Address must have a User. So in essence, the Address belongs to User.
Create two tables users and addresss, and add user_id to the address table as a column.
Then you define your relationships:
// In your User.php model
public function address()
{
return $this->hasOne('Address');
}
// In your Address.php model
public function user()
{
return $this->belongsTo('User');
}
Note when you use the correct notation, you can just define the model name, and not specify the pivot column. That is why I have defined the class addresss with an extra 's' to make it plural. I personally don't care about the spelling and rather Laravel take care of everything. Otherwise read the documentation on how to define the pivot column
Then you can use associate easily:
$user = new User();
// Fill $user however you want
$address = new Address();
// Fill $address however you want
$user->associate($address);
$user->save();
I was able to figure it out!
I wound up utilizing the Ardent package to help me validate my models before they hit the save method.
if my models didnt validate i will return all the errors to the user.
If they did validate my models would be created.
As for the association I am using the has many relation ship on the User and belongs to on the Address.
I used the following to save the address to the user
$address = $user->address()->save($address);
however I could only preform this after the initial user object was saved.
Thanks for all the responses guys they lead me in the right direction!