Here we go again, everytime I write a new policy it doesn't work for unknown reasons.
I have a voting system where I have a pivot table for votes that references the model and the user along with extra columns ('up_voted', 'down_voted').
My relations are working and if I write this code to test I get it all ok. I set in the DB an example vote for model id = 1 by the user so this code will return 'user voted' while modifying the id to 2,3, 4 whatever it will return 'user didn't vote'.
$model_id = 1;
if($user->model_votes->contains('model_id', $model_id)){
dd('user voted');
}else{
dd("user didn't vote");
}
so I thought ok I will make a policy for this and this is my policy which I correctly registered in AuthServiceProvider:
namespace App\Policies;
use App\Model;
use App\User;
class ModelPolicy
{
public function voteModel(User $user, Model $model)
{
if($user->model_votes->contains('model_id', $model->id)){
return false;
}else{
return true;
}
}
}
so in the controller I have this:
$model = Model::findOrFail($id);
$this->authorize('voteModel', $model);
and of course it doesn't work and always returns an exception no matter what
The working code you put contains this condition:
$user->model_votes->contains('model_id', $model_id)
So I assume that you just have to put the very same condition in your Policy:
public function voteModel(User $user, Model $model)
{
return $user->model_votes->contains('model_id', $model->id);
}
Related
I have a model called RealEstate, this model has a relation with another model called TokenPrice, I needed to access the oldest records of token_prices table using by a simple hasOne relation, So I did it and now my relation method is like following:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class RealEstate extends Model
{
public function firstTokenPrice(): HasOne
{
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
}
By far it's fine and no complexity. But now, I need to involve another relation into firstTokenPrice.
Let me explain a bit more:
As my project grown, the more complexity was added it, like changing firstTokenPrice using by a third table called opening_prices, so I added a new relation to RealEstate called lastOpeningPrice:
public function lastOpeningPrice(): HasOne
{
return $this->hasOne(OpeningPrice::class)->latestOfMany();
}
So the deal with simplicity of firstTokenPrice relation is now off the table, I want to do something like following every time a RealEstate object calls for its firstTokenPrice:
Check for lastOpeningPrice, if it was exists, then firstTokenPrice must returns a different record of token_price table, otherwise the firstTokenPrice must returns oldestOfMany of TokenPrice model.
I did something like following but it's not working:
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasOne;
class RealEstate extends Model
{
public function lastOpeningPrice(): HasOne
{
return $this->hasOne(OpeningPrice::class)->latestOfMany();
}
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
return $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany();
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
}
I have checked the $this->hasOne(TokenPrice::class)->where('amount', $lop->amount)->oldestOfMany() using by ->toSql() method and it returns something unusual.
I need to return a HasOne object inside of firstTokenPrice method.
You can use ofMany builder for that purpose:
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount); // this is just a helper function that inserts a new token price into `token_prices` table, if there was none exists already with selected amount
return $this->hasOne(TokenPrice::class)->ofMany([
'id' => 'min',
], function ($query) use ($lop) {
$query->where('amount', $lop->amount);
});
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
I used ->oldest() with a custom scope called amounted in TokenPrice model:
class TokenPrice extends Model
{
public function scopeAmounted(Builder $query, OpeningPrice $openingPrice): Builder
{
return $query->where('amount', $openingPrice->amount);
}
/....
}
And then changed my firstTokenPrice
public function firstTokenPrice(): HasOne
{
$lop = $this->lastOpeningPrice;
if ($lop) {
TokenPriceHelper::getOrCreateFirstToken($this, $lop->amount);
return $this->hasOne(TokenPrice::class)->amounted($lop)->oldest();
}
return $this->hasOne(TokenPrice::class)->oldestOfMany();
}
It's working, but I don't know if it's the best answer or not
Documentation says:
$user = User::find($user_id);
$user->delete();
This doesnt work, however ProductColor::find($color_id) working. $color->delete() Doest return anything, DELETE FROM query doesn't even execute (as seen in debug bar).
But I can delete record with:
ProductColor::destroy($color_id);
Must be something I overlooked earlier, I'm new to Laravel.
I'm using store also, and it working as expected
public function store(Request $request)
{
$color = new ProductColor();
$color->name = $request->color_name;
$color->order = $request->color_order;
$saved = $color->save();
if ($saved) {
return back()->with('message:success', 'Ok');
} else {
return back()->with('message:error', 'Error');
}
}
To sum up
This WORKS
public function destroy($color_id)
{
$deleted = ProductColor::destroy($color_id);
if ($deleted) {
return back()->with('message:success', 'Deleted');
} else {
return back()->with('message:error', 'Error');
}
}
This NOT
public function destroy($color_id)
{
$color = ProductColor::find($color_id);
$color->delete();
}
My Model
<?php
namespace Modules\Shop\Entities;
use Illuminate\Database\Eloquent\Model;
use Modules\Languages\Entities\Language;
class ProductColor extends Model
{
protected $fillable = [];
protected $table = 'product_colors';
}
Sorry, I've figured out the problem. My mistake to post this question.
What I tried to do:
$color = new ProductColor();
$color->find($color_id);
$color->delete();
Should be:
$color = ProductColor::find( $color_id );
$color->delete();
My problem was that I was scared about the IDE complaining about using non-static method 'find'
Please check your model class if you have added soft delete option in that case your record will not be deleted from the database.
Your code is fine - the docs show exactly what you are doing.
If there is no error, and the color is not deleted as expected, then $color_id is not being passed as expected. Try using findOrFail, or add some other check that you found the expected model.
DB::table('pykcodes')
->where('user_id', $user_id)
->delete();
This works directly without using the model.
Just make sure you call use DB; from the top.
My problem was, the name of the property inside the uri on the routes file was incorrect:
Route::delete('/foo/{fo3o}', [DollyController::class, 'delete']);
-----^
I don't know why the controller method was working:
public function delete(Foo $foo)
{
$foo->delete();
return ['message' => 'success'];
}
After correcting it, the problem was solve and the delete method started working again:
Route::delete('/foo/{foo}', [DollyController::class, 'delete']);
------^
You have to add SoftDeletes in User Model:
...
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable
{
use SoftDeletes;
protected $dates = ['deleted_at'];
...
I have a pivot table of users_operators.
I want to grab the operator_id of the user.
This is how i do this now, but its seems like verbose way.
if (Auth::user()->type === 'operator') {
$user = Auth::user();
// There is a better way to do this?
$operator_id = $user->operator[0]['pivot']['operator_id'];
Session::put('operatorId', $operator_id);
}
class Operator extends \Eloquent
{
public function users() {
return $this->belongsToMany('User');
}
}
class User extends \Eloquent
{
public function operator() {
return $this->belongsToMany('Operator');
}
}
I'm, battling insomnia and not functioning at 100%, but you should be able to get away with $user->operator->id based on what I'm interpreting your models to be (it looks like you had a typo when you copied them into the question).
If that doesn't work, you might want to check out the "Dynamic Properties" section in the Eloquent docs for more info, if you haven't already.
I'm a real newbie to Laravel but I'm loving it so far. I'm struggling on thing however, I want to retrieve the data for the user that is logged in and I am not sure how to go about this.
I have a few tables but I'll keep it basic for now, I have projects table and a users table, I've defined the relationships between these two in the models as so:
user.php
public function projects() {
return hasMany('project');
}
project.php
<?php
use Illuminate\Database\Eloquent\ModelNotFoundException;
class Project extends Eloquent
{
public function user()
{
return belongsTo('user');
}
}
I know I can do the following to retrieve all projects in the database with a foreach loop, however this doesn't retrieve the logged in users projects:
$projects = DB::table('projects')->get();
I saw one tutorial which wasn't very in depth but he said to access the model query I would have to use the following command:
$project = User::all()->projects;
However this hasn't worked either. Can anyone point me into the right direction with real tutorials or post simple examples?
Thanks in advance
Those are the projects of your logged in user:
if (Auth::check())
{
$projects = Auth::user()->projects;
}
And this must be in your relation:
class User extends Eloquent
{
public function projects() {
return this->hasMany('Project');
}
}
You also need to add $this to your Project relation:
class Project extends Eloquent
{
public function user()
{
return $this->belongsTo('User');
}
}
I was creating a like system for my website. in this I wanted one user can only like one time for a post. and a post can be liked by many user. Also many user can like many post.
So if I guess it right, It is a many to many reletionship.
in this context,
I create the following table
... users table:
id
name
....
posts table :
id
post
...post_likes table
id
user id
poost_id
Now I am having the following model for
user :
class User extends SentryUserModel {
public function post_likes()
{
return $this->has_many('Post_like', 'id');
}
}
post :
class Post extends Eloquent {
public function post_likes()
{
return $this->has_many('Post_like', 'id');
}
}
post_like :
class Post_like extends Eloquent {
public function posts()
{
return $this->belongs_to('Post', 'post_id');
}
public function users()
{
return $this->belongs_to('User', 'user_id');
}
}
now when I am going to insert into the database (for post_likes table) I am getting an error called
Illuminate \ Database \ Eloquent \ MassAssignmentException
user_id
Also I want to know is there any way to inset into database like
$user->like()->save($user); ?????
Thank you in advance. Happy coding . \m/
I'll start with a basic issue, firstly you might want to make sure all your tables are lower case (still as a snake case as well), it's not required but it's ultimately how it's expected to be with Laravel so it makes life easier to keep with that. Also a note to the wise, like Class names, database tables are typically in the singular so user instead of users
Secondly yes you can do an insert with $user->post_likes()->save($debate); as your post_likes method on the user class returns has_many.
Thirdly, your design of the Post_like class is a bit off, you could be better off make it like so:
class PostLike extends Eloquent { // note that PostLikes is a more standard naming for a class, they should ideally be camel case names but with all capitals for words
protected $table = 'post_like'; // specifies the table the model uses
public function post() // this should be singular, the naming of a belngs_to method is important as Laravel will do some of the work for you if let it
{
return $this->belongs_to('Post'); // by naming the method 'post' you no longer need to specify the id, Laravel will automatically know from the method name and just adding '_id' to it.
}
public function users()
{
return $this->belongs_to('User');
}
}
Fourthly, your other classes could be better as:
class Post extends Eloquent {
public function post_likes()
{
return $this->has_many('PostLike'); // doesn't require you to specify an id at all
}
}
I can't exactly tell you why you're getting that mass assign error, your post is a bit garbled and doesn't look like you've included the code that actually causes the exception? I have a feeling though is that you're trying to do an insert for multiple database rows at one time but haven't defined a fillable array for PostLike such as with here: http://four.laravel.com/docs/eloquent#mass-assignment
According to Laravel 5:
User Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model {
public function post_likes()
{
return $this->hasMany('App\PostLike');
}
}
Post Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model {
public function post_likes()
{
return $this->hasMany('App\PostLike');
}
}
PostLike Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class PostLike extends Model {
protected $table = 'post_like';
public function posts()
{
return $this->belongsTo('App\Post');
}
public function users()
{
return $this->belongsTo('App\User');
}
}
and if you want to save the post_like data then:
$inputs['post_id'] = 1;
$inputs['user_id'] = 4;
$post_like = PostLike::create($inputs);
Hope this helps!!