I have a page where I display a list of projects, including a count of a relationship(rmgs). This is the query:
Project::select('id', 'number', 'name', 'status')
->withCount(['rmgs as project_rmg_submitted' => static function ($query): void {
$query->where('submitted', true);
}])
->withCount(['rmgs as project_rmg_unsubmitted' => static function ($query): void {
$query->where('submitted', false);
}])
->get()
But I need the count only for projects that have the status='Approved'.
I just found the when method, but this check an external flag. I need to check the condition on the model.
Project::select('id', 'number', 'name', 'status')
--- this should be conditional for project.status='Approved' ----
->withCount(['rmgs as project_rmg_submitted' => static function ($query): void {
$query->where('submitted', true);
}])
->withCount(['rmgs as project_rmg_unsubmitted' => static function ($query): void {
$query->where('submitted', false);
}])
----------------------------------------------------------
->get()
Have you tried?
Project::select('id', 'number', 'name', 'status')
->withCount(['rmgs as project_rmg_submitted' => static function ($query): void {
$query->where('submitted', true);
}])
->withCount(['rmgs as project_rmg_unsubmitted' => static function ($query): void {
$query->where('submitted', false);
}])
->where('status','=','Approved')
->get();
Related
I have simple comment rating logic now.
For example i have following controller :
public function rating_change(Request $request, Comment $comment)
{
if ($request['action'] == 'up') {
$comment->positive_rating = $comment->positive_rating + 1;
} else if ($request['action'] == 'down') {
$comment->negative_rating = $comment->negative_rating + 1;
}
$comment->save();
return ['positive' => $comment->positive_rating, 'negative' => $comment->negative_rating];
}
And the route for that method:
Route::put('/comments_rating/{comment}', function (Comment $comment, Request $request) {
$commentController = new CommentController();
return $commentController->rating_change($request, $comment);
});
Model:
class Comment extends Model
{
use HasFactory;
protected $fillable = [
'body',
'user_id',
'item_id'
];
protected $casts = [
'user_id' => 'integer',
'item_id' => 'integer',
];
public function author()
{
return $this->belongsTo(User::class, 'user_id');
}
public function post()
{
return $this->belongsTo(Items::class, 'id');
}
}
And resource:
return [
'id' => $this->id,
'user_id'=>$this->user_id,
'body'=>$this->body,
//https://github.com/jenssegers/date
'created_at' => Date::parse($this->created_at)->diffForHumans(),
'updated_at' => $this->updated_at->format('Y-m-d H:i'),
'author'=>[
'id'=>$this->author->id,
'name'=>$this->author->name,
],
'rating'=>[
'positive'=>$this->positive_rating,
'negative'=>$this->negative_rating
]
];
The current purpose to prevent change rating by the same user multiple times.(Server side block)
And return the following flag (changed or smth) to frontend.
How should i to do this?
Should i use the separate table and store all user actions to get flag of changed them in all my comments?
Should i use the https://laravel.com/docs/8.x/redis for that purpose or sql is enough?
Maybe there is some built in laravel solutions or libraries?
I use laravel sanctum to authorize.
I am beginner webdeveloper.
I have small problem my model.
I have this migration and model:
Schema::create('stopwatches', function (Blueprint $table) {
$table->increments('id');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
Schema::create('timecycles', function (Blueprint $table) {
$table->increments('id');
$table->integer('timecycleable_id');
$table->string('timecycleable_type');
$table->integer('case_id')->unsigned();
$table->foreign('case_id')->references('id')->on('case_instances')->onDelete('cascade');
$table->boolean('status')->default(0);
$table->integer('worked_time')->default(0);
$table->timestamps();
});
class Stopwatch extends Model
{
protected $fillable = [
'case_id',
'user_id'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
'user_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function timeCycle()
{
return $this->morphMany(Timecycle::class, 'timecycleable');
}
public function caseInstance()
{
return $this->belongsTo(CaseInstance::class, 'case_id');
}
class Timecycle extends Model
{
protected $fillable = [
'case_id',
'timecycleable_id',
'timecycleable_type',
'status',
'worked_time'
];
protected $casts = [
'id' => 'int',
'case_id' => 'int',
];
protected $dates = [
'created_at',
'updated_at'
];
public function stopwatch()
{
return $this->morphTo();
}
}
In timecycles I have 2 record with status = 0 and status = 1: https://ibb.co/5vyh316
I need my stopwatches with only one timecycles with status = 1.
I make this code:
return $this->stopwatch::with(['timeCycle', 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', \Carbon\Carbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
In result I have booth items: https://ibb.co/WnJ58Kc
What's wrong in my code?
How can I repair it?
Please help me.
You're actually quite close, but whereHas() doesn't affect the loaded records. Use the same clause on your with() statement:
return $this->stopwatch::with(['timeCycle' => function ($q) {
$q->where('status', 1); // If you only want 1, you can do `->limit(1)` as well
}, 'caseInstance'])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', \Carbon\Carbon::now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($q) {
$q->where('status', 1);
})
->get();
Now, when looping over your data, each $record->timeCycle will only include whatever is specified in the with() clause.
It's likely the problem is generated by the with('timeCycle') clause. If you want to constraint your query by a relation, you need to specified it in both the whereHas and the with(), otherwise the eager loading will fetch all the elements making the whereHas irrelevant. Try this:
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => function ($query) {
$query->where('status', 1);
}
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', function ($query) {
$query->where('status', 1);
})
->get();
Of course, given both constraints are equal, you could store it in a variable and pass it to both methods:
$timeCycleContraint = function ($query) {
$query->where('status', 1);
};
return $this
->stopwatch::with([
'caseInstance',
'timeCycle' => $timeCycleContraint
])
->where('user_id', Auth()->user()->id)
->where('updated_at', '<=', now()->subSeconds(30)->toDateTimeString())
->whereHas('timeCycle', $timeCycleContraint)
->get();
Hi I have more than 500k records in items table Its takes more than 9 seconds to execute this query ineed to make it milliseconds to execute this query using mysql index
$products = \App\items::with([
'item_store' => function($query) {
$query->select('size', 'item_id', 'item_store_id');
},
'pics' => function($query) {
$query->select('img_url', 'item_id');
},
'brand' => function($query) {
$query->select('item_id', 'brand_id');
},
'brand.brand' => function($query) {
$query->select('brand_id', 'brand_name');
}
])
->select('item_id', 'short_name', 'price', 'price_above')
->orderBy('Price', 'Asc')->whereIn('category_id', $arr)
->groupBy('Sku')
->paginate(20);
my database structure is [st] https://screenshots.firefox.com/JAmaKENMYRhQkEjx/ourweds.com
this is item table migration
Schema::create('item', function (Blueprint $table) {
$table->bigIncrements('item_id');
$table->string('item_name');
$table->integer('Sku');
$table->text('Description');
$table->text('short_description');
$table->text('category_id');
$table->string('color');
$table->double('price');
$table->double('indian_price');
$table->string('old_price');
$table->string('indian_old_price');
$table->timestamps();
});
item eloquent model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class items extends Model
{
//
protected $table = 'items';
protected $primaryKey = 'item_id';
protected $fillable = [
'category_id',
'item_name',
'Sku',
'Description',
'short_description',
'color',
'kik_cash_percentage',
'status',
'price',
'price_old',
'indian_price',
'short_name',
'price_above',
'short_name_alter',
'availability'
];
public function pics(){
return $this->hasOne( 'App\item_pics', 'item_id' );
}
public function item_store()
{
return $this->hasMany('App\item_store','item_id');
}
public function category()
{
return $this->belongsTo('App\categories','category_id');
}
public function brand()
{
return $this->hasOne('App\item_has_brand','item_id');
}
}
I made a Models controller and use it as resources for almost all my Model. Now, when I try to get the data of a model and the related models, Laravel replace upper case letter with an underscore and the lower case letter. I need to let it with the upper case.
So there is the model where I got the issue at App\Models\Rate:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Rate extends Model
{
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'rates';
protected $fillable = [
'institution_id',
'name',
];
protected $info = [
'relations' => [
'rateRistournes' => [
'model' => 'RateRistourne',
'type' => 'hasMany',
],
'rateRows' => [
'model' => 'RateRow',
'type' => 'hasMany',
],
'rateTables' => [
'model' => 'RateTable',
'type' => 'hasMany',
],
],
'rules' => [
],
'hashid' => false,
];
public function getRelations()
{
return $this->info['relations'];
}
public function getRules()
{
return $this->info['rules'];
}
public function useHashid()
{
return $this->info['hashid'];
}
public function institution()
{
return $this->belongsTo(Institution::class);
}
public function rateTables()
{
return $this->hasMany(RateTable::class);
}
public function rateRows()
{
return $this->hasMany(RateRow::class);
}
public function rateRistournes()
{
return $this->hasMany(RateRistourne::class);
}
}
And this is the function that contain the query into ModelsController:
public function show($name, $id)
{
$data = $this->retrieveModelAndRelations($name, $id);
if (is_null($data)) {
return $this->sendError('Model not found.');
}
return $this->sendResponse($data->toArray(), 'Model retrieved successfully.');
}
private function retrieveModelAndRelations($name, $id)
{
$modelName = 'App\Models\\'.$name;
$model = new $modelName;
if ($id === 'null') {
...
} else {
$data = $modelName::when(isset($model->getRelations()['customer']), function($query) {
return $query->with('customer');
})...
})->when(isset($model->getRelations()['rateTables']), function($query) {
return $query->with(array('rateTables' => function($q) {
$q->orderBy('cashStart', 'ASC');
}));
})->when(isset($model->getRelations()['rateRows']), function($query) {
return $query->with(array('rateRows' => function($q) {
$q->orderBy('rate', 'ASC');
}));
})->when(isset($model->getRelations()['rateRistournes']), function($query) {
return $query->with(array('rateRistournes' => function($q) {
$q->orderBy('ristourne', 'ASC');
}));
})->find($id);
}
return $data;
}
And there is the result into the console:
created_at:(...)
deleted_at:(...)
id:(...)
institution_id:(...)
name:(...)
rate_ristournes:Array(1)
rate_rows:Array(1)
rate_tables:Array(1)
The 3 last line should be:
rateRistournes:Array(1)
rateRows:Array(1)
rateTables:Array(1)
Is there a way to force laravel to keep the relation key as I wrote it?
Something under the hood change the name and I don't know how to bypass it.
Change $snakeAttributes:
class Rate extends Model
{
public static $snakeAttributes = false;
}
I get an error while using getAttributes method : "Call to a member function getAttributes() on a non-object".
Now, In my Controller:
$notifications = Notifications::return_new()->getAttributes();
var_dump($notifications);
In model
public static function return_new(){
return Notifications::find()->where(['is_seen' => 0])->all();
}
Now, the Yii docs say that getAttribute() takes an array as a parameter, so I've tried
$notifications = Notifications::return_new()->getAttributes('text');
but it still persists with the same error. Any help?
Here is the model
<?php
namespace frontend\models;
use Yii;
*/
class Notifications extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'notifications';
}
public function rules()
{
return [
[['created_on', 'user_id', 'text'], 'required'],
[['user_id'], 'integer'],
[['created_on'], 'safe'],
[['text'], 'string', 'max' => 255]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'created_on' => 'Created On',
'user_id' => 'User ID',
'text' => 'Text',
];
}
public static function count_new()
{
$new = Notifications::find()->where(['is_seen' => 0])->all();
return count($new);
}
public static function return_new(){
return Notifications::find()->where(['is_seen' => 0])->all();
}
public function return_all(){
return Notifications::find()->all();
}
public static function checkst(){
return Notifications::find()->where(['id' => 3])->one();
}
public function return_by_date () {
// write something here.
}
}
If you use all() you obtain a collection of models and then you should refere to
Notifications::return_new()[0]->getAttributes();
otherwise you can
public static function return_new(){
return Notifications::find()->where(['is_seen' => 0])->one();
}
and in this case you can use
$notifications = Notifications::return_new()->getAttributes();