Defining a Relationship on User - laravel

I'm developing a package that is using the user model in the main app.
I need to add a relationship to the user model that links to one of my packages models.
How can I do this?
Create a new model in my package called user and namespace it and define the relationship here?
Is there a better way?
I do not wish for who ever uses the package to go in and add the relationship themselves to the user model.

You should create a trait for that, and ask you package's users to add it in:
namespace MyAwesome\Package;
trait PerishableTrait {
public function perishables()
{
return $this->hasMany('MyAwesome\Package\Perishable');
}
}
Then tell your users to just add this single line to their User model:
class User extends ... {
use MyAwesome\Package\PerishableTrait;
}

Related

How do I use a Laravel dynamic relationship?

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!

Laravel restrict content based on customer/user/tenant

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

Laravel 4 Use the same Model and Controller for 12 lists for selects

I have to meke models, controllers and views for 12 tables. They have all the same structure id, name, order.
I was thinking and maybe using:
Controller
index($model)
$model::all()
return View::make(all_tables,compact('model'))
edit($model,$id)... and so on.
But and don't know if there's a way for using only one model.
Did anybody do anything like this?
Any idea?
Thanks
Although each model has the same table structure, what you're trying to achieve would not be advisable as you'd lose a lot of the fluent capabilities of Laravel's Eloquent ORM.
Regarding the controller, this would work:
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class GenericModelController extends Controller
{
public function loadModelById($model, $id)
{
$instance = \App::make('App\\' . ucfirst($model));
return $instance->find($id);
}
}
You'll need the following route:
Route::get('show/{model}/{id}', 'GenericModelController#loadModelById');
Example, to load a user with an id of 1:
http://www.yourdomain.com/show/user/1
Edit: I just saw that you're using Laravel 4, so the syntax for defining a route will be a little different I believe but the general concept will still work. Testing in Laravel 5 and works perfectly.
You should get get some idea from here.Please use the link below.
https://scotch.io/tutorials/a-guide-to-using-eloquent-orm-in-laravel
// app/models/Bear.php
class Bear extends Eloquent {
// MASS ASSIGNMENT -------------------------------------------------------
// define which attributes are mass assignable (for security)
// we only want these 3 attributes able to be filled
protected $fillable = array('name', 'type', 'danger_level');
// DEFINE RELATIONSHIPS --------------------------------------------------
// each bear HAS one fish to eat
public function fish() {
return $this->hasOne('Fish'); // this matches the Eloquent model
}
// each bear climbs many trees
public function trees() {
return $this->hasMany('Tree');
}
// each bear BELONGS to many picnic
// define our pivot table also
public function picnics() {
return $this->belongsToMany('Picnic', 'bears_picnics', 'bear_id', 'picnic_id');
}
}
I find a simple way.
Only one model, one controller and one view(index,edit, etc) too.
A single table with
id, name of list, value (name to appears in the list)
Yo pass can pass to de view all the values per list, and for any list in the table you can create de select if it's no empty.

Define model relationships in complex business logic in Laravel

Now I have those business logic, but don't know how to define it in Laravel.
First, there are two basic model named contact and project, and contact and project model owns many-to-many relations so I defined them like below:
class Contact extends Model{
public function projects(){
return $this->belongsToMany('App\Project', 'proj_staff')
->withPivot('role', 'superior');
}
}
And the same as Project:
class Project extends Model{
public function contacts(){
return $this->belongsToMany('App\Contact', 'proj_staff')
->withPivot('role', 'superior');
}
}
As you see, every contact has a superior in his project or not, so the question comes with it that how can I define a relation to get access to superior like this: $contact->projects[0]->superiors, and the superiors has better return a Model Collection rather than just id.
Thx any way.
You are accessing projects from your contacts & you want to access projects & contacts pivot table proj_staff info from your projects model.
So you have to create another relation in your in your Project
model to access the data from your pivot table
class Project extends Model{
public function contacts(){
return $this->belongsToMany('App\Contact', 'proj_staff')
->withPivot('role', 'superior');
}
//your project table has one to many many relationship with proj_staff table
public function superiors(){
return $this->hasMany('App\ProjStaff', 'superior', 'superior');//set relation keys I assume it's superior is local and foreign key
}
}
//Create ProjStaff Pivot Table Model under app directory same level with your Contact model
class ProjStaff extends Model{
//add fillable
//add table name
}
Now you can easily access superior like $contact->projects[0]->superiors->pluck('superior')->all()

firstorcreate is not working for new entry laravel

I am new to laravel and using ardent for creating models, I have below base class for all model.
class MainModel extends Ardent {
//with some common methods
}
and now i have sub model class such user
class User extends MainModel
{
//with user table and other methods related to user
}
and also I have repository for user ->User Repository and I am calling firstOrcreate method to check(user entry) and create user.
if user is exists in database then above method is working fine ,its returning existing user object but if user is not exists in database it is not creating user also its not inserting entry to table.is I am doing wrong here?
You just need to save the user after calling firstOrCreate():
$user->save();
You may want to check if the user doesn't exist before that:
if (!$user->id) $user->save();

Resources