I have created a query in SQL and it works quite well.
SELECT learning_content_number,
course,
count(required) as required,
count(overdue) as overdue,
count(status) as status,
count(completion_date) as completion_date
FROM hse_leatros
GROUP BY learning_content_number
Now I want to translate it in Laravel 8 Eloquent. This script works, but I am missing the information about the course.
$courses = Leatro::groupBy('learning_content_number')
->selectRaw('count(required) as required, learning_content_number')
->selectRaw('count(overdue) as overdue, learning_content_number')
->selectRaw('count(status) as status, learning_content_number')
->selectRaw('count(completion_date) as completion_date, learning_content_number')
->get();
How can I enter the in the code that it is transferred with?
My DB-Table structur:
$table->id();
$table->integer('employee_id')->nullable();
$table->string('course')->nullable();
$table->string('required')->nullable();
$table->string('mandatory')->nullable();
$table->string('status')->nullable();
$table->string('due_date')->nullable();
$table->string('completion_date')->nullable();
$table->string('overdue')->nullable();
$table->string('learning_content_number')->nullable();
$table->string('assigned_date')->nullable();
$table->string('assigned_mechanism')->nullable();
$table->string('cost_centre_id')->nullable();
$table->string('hash')->nullable();
$table->timestamps();
$table->softDeletes();
You need just add ->select('learning_content_number', 'course'):
$courses = $db::table('hse_leatros')
->groupBy('learning_content_number', 'course')
->select('learning_content_number', 'course')
->selectRaw('count(required) as required')
->selectRaw('count(overdue) as overdue')
->selectRaw('count(status) as status')
->selectRaw('count(completion_date) as completion_date')
;
echo $courses->toSql();
print_r($courses->get());
Laravel QueryBuilder online
Related
As can be seen in the linked image, I want to query the records that have the same chapter number (skipping the zeros). Let's say I have 50 chapters, so the query will yield 50 sets, each set corresponding to certain column value i.e. chapter number.
How can I limit the query to that in my Laravel controller?
Get chapter groups, Like drawing in the image
$chapters = Translation::where('chapter', '!=', 0)->get()->groupBy('chapter');
Without pagination:
$chapters = Translation::where('chapter', '!=', 0)->get()->groupBy('chapter');
With pagination :
$posts = Translation::where('chapter', '!=', 0)->orderBy('chapter', 'ASC')->paginate($request->get('per_page', 2));
$grouped_by_chapter = $posts->mapToGroups(function ($post) {
return [$post->chapter => $post];
});
$posts_by_chapter = $posts->setCollection($grouped_by_chapter);
for more: https://laravel.com/docs/8.x/collections#method-groupby
Without knowing more about your project setup, I'd say:
$chapters = DB::table('translations')
->select('chapter')
->distinct()
->where('chapter', '<>', 0)
->get();
If you use eloquent models:
$chapters = Translations::get()
->pluck('chapter')
->flatten()
->filter()
->values()
->all();
In the Elequent model, you can create a hasMany relation to 'translations',
class Chapter extends Model
{
public function translations()
{
return $this->hasMany(Translation::class, 'chapter');
}
and then retrieve the 'Chapter' models with translations.
$chapters = Chapter::with('translations')->get()
A lot of these answers are correct, but I thought I'd offer a different approach.
1. Create a new table
Consider creating an additional table called chapters.
Do this by using the command:
php artisan make:model Chapter -m
This'll create a model and migration.
The migration will look like this:
Schema::create('chapters', function (Blueprint $table) {
$table->id();
$table->integer('number')->unsigned();
$table->string('heading');
$table->timestamps();
});
2. Add the foreign key to your old table
Then modify your model from your screenshot. From here on, I'll assume the same as everyone else, that this table is called translation, with a model called Transaltion.
Your new migration should look like this:
Schema::create('translations', function (Blueprint $table) {
$table->id();
$table->foreignId('chapters_id')->constrained()->onUpdate('cascade')->onDelete('cascade');
$table->string('translation');
$table->timestamps();
});
3. Add the relationship to the models
Translation model
public function chapters()
{
return $this->belongsTo(Chapter::class);
}
Chapter model
public function translations()
{
return $this->hasMany(Translation::class);
}
4. Using the new relationship
Instead of having to use groupBy, or any of the other methods, you now can query on each heading.
An example of some of those below.
4.1 How many chapters do we have?
Chapter::count();
4.2 How many sentences are there in Chapter 1?
Chapter::where('number', 1)->translations()->count();
// or if you want to get a Collection of them
Chapter::where('number', 1)->translations;
// or if you just want a certain few columns
Chapter::where('number', 1)->translations()->select('translation', 'sentence')->get();
4.3 How do I get all chapters and corresponding translations?
$chapters = Chapter::with('translations')->get();
Then in your blade view, do:
#foreach ($chapters as $chapter)
<h1>{{ $chapter->heading }}</h1>
<p>Sentences:</p>
#foreach ($chapter->translations as $sentence)
<p>{{ $sentence }}</p>
#endforeach
#endforeach
Assuming you have a Translation model and want to use Eloquent:
$chapters = Translation::where('chapter', '!=', 0)->get()->groupBy('chapter');
The above says get all Translation where the Chapter they are associated to is not Chapter zero and group all translations by the chapter column. So if you have 50 chapters you'll have 50 collections each with their translations contained within.
If you just want specific columns, you can use select() and provide it with only the columns you want.
As u guys can see in Image Above, i want to create referral_system that user can register and input referral_user from affiliate users.
And Referral_Code is unique for every user.
My Problem is I cant track Whom that code is.
My User Schema
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('referrer_id')->nullable();
$table->foreign('referrer_id')->references('id')->on('users');
$table->string('referral_code')->unique()->nullable();
$table->string('referred_by')->nullable();
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
My User Model
public function referrer()
{
return $this->belongsTo(User::class);
}
public function referrals()
{
return $this->hasMany(User::class);
}
In My UserController
$referrer = User::where('name', auth()->user()->name)->first();
$user = new User();
$user->name = $request->name;
$user->referral_code = substr(uniqid(), 0, 8); // for unique id
$user->email = $request->email;
$user->referrer_id = $referrer ? $referrer->id : null;
$user->role = $request->role;
$user->password = bcrypt($request->password);
$user->save();
return response()->json([
'created' => true,
]);
Hope u guys will give me some idea and if u notice mistake in my code, pls correct me, I'll appreciate of all ur help.
Thanks...
I believe you're confusing Laravel relationships. hasOne, belongsTo, etc are not designed to be worked with in the same model. Basically what you're saying in Users model is that "User has a User where user_id = id" which makes no sense.
I have no idea how you've designed your sql tables, I recommend you to split your entities in distinct parts and have pivot tables which binds them: users, affiliates, referrals
- users table have : "id"
- affiliates table have: "id", "refferal_code"
- refferals table have : "id", "affiliate_id", "user_id", "refferal_code"
You tie a user with an affiliate through refferals table, through their IDs.
Then create relationships between those. You may want to read more about Eloquent relationships as well. Hope this answer helps you.
I have a simple function to accept a friend's request:
public function acceptFriend($id){
$user = User::find($id);
$sender = Auth::user();
$sender->acceptFriendRequest($user);
return redirect()->back();
}
It work's correctly but if other user send a friend's request, he send a notification. I want to mark as read it after accept request but I have a problem.I don't know how I can do query building to check this one notify. I know I can make a new function and like attirute use notify id but user of my website can accept request not only in notify list but in user's profile too.
I thought about read information form "data" column from "notifications" table but I have a problem. I try a few of query buildings:
$hello = auth()->user()->unreadNotifications->where('notifiable_id', Auth::user()->id)
->where('data->arr->id', '12')->first();
or
$hello = auth()->user()->unreadNotifications->where('notifiable_id', Auth::user()->id)
->where('data', '%12%')->first();
But it doesn;t works. "12" is id of sender,
The table structure is the normal notifications structure:
Schema::create('notifications', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('type');
$table->morphs('notifiable');
$table->text('data');
$table->timestamp('read_at')->nullable();
$table->timestamps();
});
The data column will contain an array such as:
{
"title":"Something",
"arr":{
"id":12,
"name":"HelloWorld",
"avatar":null
}
}
You will need the Query Builder equivalent of a LIKE query.
->where('data', '%12%') will generate SQL: data = '%12%' returning no results.
->where('data', 'like', '%12%') will generate SQL: data like '%12%' which should work.
I'm working in a biggest application ( more than 1 million users ) and I try to get the ranking of each user in the scoreboard section but had this problem: the result is very very slow
This is the architecture of my database:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
...
});
Schema::create('topics', function (Blueprint $table) {
$table->increments('id');
...
});
The topics table have than 20 row
Schema::create('user_scores', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('topic_id')->unsigned();
$table->unique(['user_id', 'topic_id']);
$table->float('timer');
$table->integer('score');
});
The query to make rank for users
User::where('type',0)->get()->each(function ($user) {
$user->topics= $user->scores->sum('score');
$user->timing= $user->scores->sum('timer');
})->sort(function ($a, $b){
return ($b->topics - $a->topics) == 0
? ($a->timing - $b->timing)
: ($b->topics - $a->topics);
})->values()->each(function($user, $key){
$user->rank = $key +1;
});
Any optimization should I make the get the result quicker? Thanks.
As soon as you call get(), all(), find() or first() on a query builder, you'll ask the Eloquent engine to perform the query and return you the result. So in your case, all the sorting and grouping is performed in memory, which comes with incredibly bad performance.
What you can do is to improve your query:
User::query()
->where('type', 0)
->withCount('scores as topics')
->withCount(['scores as timing' => function ($query) {
$query->selectRaw('SUM(timer)'); // might look weird, but works...
}])
->orderBy('topics', 'desc')
->orderBy('timing', 'desc')
->get()
For the row number (or rank, or however you wanna call it), you might want to search through existing questions and answers. Answering that as well would be too much for this answer, to be honest. Clearly you should not use your approach though, as it will also calculate the row number in memory.
But obviously it is also important what you are doing with the query results. Are you displaying one million rows to the user? If so, the bottleneck will be the browser in the end for sure. You might want to consider using pagination with paginate() instead of get().
I trying to understand laravel eloquent relationship so i created two tables. structure of tables defined in laravel migration is
for mostpopular table
Schema::create('mostpopulars',function(Blueprint $table){
$table->increments('id');
$table->integer('song_id')->unsigned();
$table->index('song_id');
$table->foreign('song_id')->references('id')->on('song_details')->delete('cascade');
});
for song_detail table
Schema::create('song_details', function (Blueprint $table) {
$table->increments('id');
$table->string('song_title');
$table->string('song_name');
$table->string('song_album');
$table->string('song_singer');
$table->string('song_musicby');
$table->string('song_location');
$table->string('song_album_image');
$table->string('song_language');
$table->string('song_lyrics',3000);
$table->timestamps();
});
then in Mostpopular model defined function for relating two table
public function song_detail()
{
return $this->hasOne('App\Song_detail','id');
}
and in controller index function i want to do something like this
$songs = Song_detail::select()->latest()->get();
$malayalamSongs = Mostpopular::select('song_id')->groupBy('song_id')->havingRaw('COUNT(*) > 2')->get();
$mp = $malayalamSongs;
dd($mp->song_detail);
but getting error
Undefined property: Illuminate\Database\Eloquent\Collection::$Song_detail
please help me to find the error and what i am trying to do is get the details of songs from song_details table where song_id occurred more than two times song_id is in mostpopular tables.
the eloquent get() will return an array, you cannot call relation method on the array.
you can use first() to replace the get() or
change
$mp = $malayalamSongs;
dd($mp->song_detail);
to
$mp = $malayalamSongs;
foreach($mp as $v)
{
dd($v->song_detail);
}