PHP Laravel 5.4.21. Eloquent save insert in first row - php

I have a problem with saving Eloquent models. For example:
$game = Game::select(['bank', 'state', 'quantity_of_players'])->find($id)->first();
$game->bank += $game->bet;
$game->quantity_of_players++;
$game->save();
As far as i know from documentation, save() should insert changed values in a row with $id, but instead it inserts in a very first row. What's an issue, and how to save it properly to my database in specified row.
Migration for this model:
public function up()
{
Schema::create('games', function (Blueprint $table) {
$table->bigIncrements('id');
$table->enum('state', ['wait', 'search', 'accept', 'play', 'finish']);
$table->smallInteger('quantity_of_players');
$table->smallInteger('ready_players');
$table->smallInteger('finished_players');
$table->integer('bank');
$table->smallInteger('bet');
});
}
Would really appreciate any help with this.
P.S. All SELECT requests works perfectly such as Eloquent create().

The find() method internally calls first(). It's also a good practise to check if the row exists before proceeding. Using findOrFail() does this for you.
$game = Game::findOrFail($id);
$game->bank += $game->bet;
$game->quantity_of_players++;
$game->save();
Edit
If you're insistent on selecting the columns even for the update. Then do this
$game = Game::whereId($id)->first(['bank', 'state', 'quantity_of_players']);

Please try the following
$game = Game::find($id);
$game->bank += $game->bet;
$game->quantity_of_players++;
$game->save();

Related

PHP/Laravel get rows with certain column values

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.

Using Laravel 5.5 how do I duplicate a column in a table with a migration?

I would like to duplicate a column on my existing seasons table using a migration in Laravel 5.5.
I can do it using SQL running these two queries:
ALTER TABLE seasons ADD uploader_channel_partner_id BIGINT NULL
then
UPDATE seasons set seasons.uploader_channel_partner_id = seasons.channel_partner_id
I am creating a system where you can transfer the ownership of videos while keeping the original uploader stored.
The up function of my migration currently just has this inside it:
Schema::create('seasons', function (Blueprint $table) {
$table->unsignedBigInteger('uploader_channel_partner_id');
$table->foreign('uploader_channel_partner_id')->references('id')->on('channel_partners');
});
EDIT:
I've made it work with this but it's slow and ugly and I'm sure there is a better way:
public function up()
{
Schema::table('seasons', function (Blueprint $table) {
$table->unsignedBigInteger('uploader_channel_partner_id')->after('channel_partner_id')->nullable();
$table->foreign('uploader_channel_partner_id')->references('id')->on('channel_partners');
});
$seasons = Season::withTrashed()->get();
foreach ($seasons as $key => $season) {
$season->uploader_channel_partner_id = $season->channel_partner_id;
$season->save();
}
}
You can use DB::raw() to force Sql to use another column instead of a string value.
Season::withTrashed()
->update([
'uploader_channel_partner_id' => DB::raw('`channel_partner_id`'),
]);

Run Update query in a migration in Laravel 5? [duplicate]

I need to add a new column in my laravel Project, no problem for this, I used the Schema::table() to update and it's ok.
Now I need to find out how many records I have on this table and update with some value.
I have the table Warrants:
Schema::create('warrant_grants', function(Blueprint $table) {
$table->increments('id');
$table->integer('warrant_plan_id');
$table->integer('shareholder_id');
});
So I created the new field with a new migration file:
Schema::table('warrant_grants',function ($table) {
$table->string('name',100);
});
Now I need to update this field name in the table with some values, for example if the table has 100 records, then I need to insert in every row the value "Warrant-X" where X is a number starting with 1 to 100.
For example:
Warrant-1, Warrant-2, ....Warrant-100.
I spent hours looking for some way to do this using Seeds but I didn't found. So basically i have two questions:
Can I use Seeds in Laravel 5 to update values or I can just insert them?
Can I create some SQL inside the Seeds (or migrations) to do this update for me?
Based on this link i found the answer: https://stackoverflow.com/a/23506744/4650792
Schema::table('warrant_grants',function ($table){
$table->string('name',100)->after('id')->nullable();
});
$results = DB::table('warrant_grants')->select('id','name')->get();
$i = 1;
foreach ($results as $result){
DB::table('warrant_grants')
->where('id',$result->id)
->update([
"name" => "Warrant-".$i
]);
$i++;
}
Thanks for the help anyway guys.
Other answers are correct. But note that if you have a lot of records, updating all of them with ORM can take time. Use raw SQL queries to do that faster.
Schema::table('warrant_grants',function ($table){
$table->string('name',100)->after('id')->nullable();
});
DB::raw("UPDATE warrant_grants SET name=name+id");
The SQL query is not exact, and you have to make it for your own DB, but you get the point.
Yes, you can perform updates/inserts/whatever in your migrations. For example:
Schema::table('warrant_grants', function($table) {
$table->string('name', 100);
});
$i = 1;
foreach (WarrantGrants::all() as $warrant_grant) {
$warrant_grant->update([
'name' => 'Warrant-' . $i
]);
$i++;
}
Another possible syntax to achieve this:
DB::table('warrant_grants')
->where('id',$result->id)
->update([
"name" => DB::raw("'Warrant-' + `name`")
]);
This allows the update to be done as one batch rather than iterating over results, and retains most of the familiar Eloquent syntax rather than falling back to just using raw SQL.
The string concatenation syntax may need to be changed depending on the SQL variant used.

selecting data with laravel eloquent relationship

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);
}

Laravel Migration - Create a new column filled from existing column

I'm trying to create a migration that makes a new column and fills it with data from existing column.
I want to turn the name column into a slug (using the helper function) and save that in a slug column.
I've tried this but no luck:
public function up()
{
Schema::table('teams', function(Blueprint $table)
{
//
$table->string('slug', 100);
});
$teams = DB::table('teams')->get();
foreach ($teams as $team)
{
$team->slug = str_slug($team->name, "-");
$team->save();
}
}
Am i being an idiot? Can i make this work?
Thanks
Assuming you have a Team model:
$teams = App\Team::all();
foreach($teams as $team) {
$team->slug = str_slug($team->name, "-");
$team->save();
}
You're trying to use Eloquent ORM syntax ($team->save) in a code that is actually using Query Builder. You'd better choose one or the other (ORM or Query building). My version uses Eloquent ORM. Of course you could have used Query Builder syntax all the way, like this:
$teams = DB::table('teams');
foreach($teams as $team) {
DB::table('teams')
->where('id', $team->id)
->update(['slug' => str_slug($team->name)]);
}
And basically a Query Builder select command (like $teams = DB::table('teams');) will return an array of stdClass objects (which have not a "save" method) , whereas Eloquent ORM select will return a collection of objects of the specified model, which do have the "save" method.
You are not using the name column, but the (empty) slug. Try this instead:
$team->slug = str_slug($team->name, "-");

Categories