Yii2 delete() without primary key - php

I want to delete a data in database with delete, but the table doesn't have the primary key
Here's the code
Table::findOne(['name' => 'Andrew', 'Age' => '25'])->delete();
Then, it shows the error
app\models\Table does not have a primary key. You should either define a primary key for the corresponding table or override the primaryKey() method.
Help me to find the way to delete without a primary key.
Thanks

You could override primaryKey() model method, so the error should disappear.
Inside app\models\Table add this method (I think that primary key should be composed with 'name' and 'Age'):
public static function primaryKey()
{
return [
'name',
'Age',
];
}

Instead of using ActiveRecord, you could use a delete command with condition:
$myCommand = Yii::$app->db->createCommand()
->delete('your_table', 'name = "Andrew" AND Age = 25 ');
$myCommand->execute();
If you want to delete all the rows that match the condition, you can use:
deleteAll( ... ) ;

Try This :
$data=Table::find()->where(['name' => 'Andrew', 'Age' => '25'])->one();
$data->delete();

Related

Can I get the primary key inside the facadesdb insert for direct use - Laravel 8

I am learning Laravel 8 and came across this problem. So, I made a controller class with FacadesDB Insert function. This is my code :
public function aksimenulis_laporan(Request $request){
$filefoto = $request->foto;
DB::table('pengaduan')->insert([
'tgl_pengaduan' => date('Y-m-d'),
'nik' => $_POST['nik'],
'isi_laporan' => $_POST['isi_laporan'],
'foto' => $filefoto->getClientOriginalName(),
'status' => '0',
]);
// isi dengan nama folder tempat kemana file diupload
$tujuan_upload = storage_path();
// upload file
$filefoto->move($tujuan_upload,$filefoto->getClientOriginalName());
return redirect('');
}
https://i.stack.imgur.com/VTJyS.png
This is my database table structure.
And I am trying to insert 'foto' with value of 'id_pengaduan' or the primary key, like using this code. Which will be PrimaryKey_OriginalFileName
'foto' => $filefoto-> 'id_pengaduan'.'_'.getClientOriginalName(),
But the problem I didn't have the value yet. Is there a way that I can value 'foto' with the primary key of the table?
you can use the insertGetId method to insert a record and then retrieve the ID:
$pengaduan_id= DB::table('pengaduan')->insertGetId([
'tgl_pengaduan' => date('Y-m-d'),
'nik' => $_POST['nik'],
'isi_laporan' => $_POST['isi_laporan'],
'status' => '0',
]);
DB::table('pengaduan')->where('id',$pengaduan_id)->update(['foto'=>$filefoto->getClientOriginalName()]);
you can not get the id before the insertion operation is done.
you also should do it in transaction, but for now, I will keep it this way.
You cannot (and shouldn't) insert a row and define its primary key. That's kind of the whole purpose of a primary key. You let SQL manage its identifiers, this is good incase of an error, so there are no duplicates in the primary key.
I'll go into eloquent since you're starting new in Laravel, this will make your life easier with DB operations.
First you'd need to make a new model for your table. You can do this using the console command:
php artisan make:model ModelName
Afterwards, navigate to your Models directory (app/Models/) and you'll find the new model ModelName.php
In there, you'd need to specify the table name and the primary key. You can do that with the these two lines:
protected $table = 'pengaduan';
protected $guarded = ['id_pengaduan'];
Your model should now look something like
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ModelName extends Model
{
use HasFactory;
protected $table = 'pengaduan';
protected $guarded = ['id_pengaduan'];
}
Save, and you might need to clear your cache. Do this by running php artisan optimize in the console.
After you are done inserting the data into a new row, you can get the primary key that was assigned to the row like this:
//using eloquent
use App\Models\ModelName;
//insert data
$insertRow = new Pengaduan;
$insertRow->tgl_pengaduan = date('Y-m-d');
$insertRow->nik = $_POST['nik'];
$insertRow->isi_laporan= $_POST['isi_laporan'];
$insertRow->foto = $filefoto->getClientOriginalName();
$insertRow->status = 0;
$insertRow->save();
//get key here
$rowId = $insertRow->pengaduan_id;
If you want to use the DB::table('table')->insert method, see OMR's answer.
If you really want to define the primary key yourself, then you'd have to run this query on the table:
SET IDENTITY_INSERT [Tablename] ON;
You can read more about this on this thread.

Lumen with Eloquent arbitrary changes all fields

Here's the code:
$row = UserFields::where(['user_id' => $user['user_id'], 'field_id' => 'myfield'])->first();
if($row)
{
$row->field_value = "new value";
$row->save();
}
Suddenly all rows field_value in that table changes to the new value and only for that user!
That's really confusing, I don't know if it's a bug in Eloquent.
Laravel eloquent, like many other ORMs is not good at handling composite primary keys. If you see the code it have
protected function setKeysForSaveQuery(Builder $query)
{
$query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery());
return $query;
}
public function getKeyName()
{
return $this->primaryKey;
}
since you seems to have a composite primary key it will only use the first field in it so all fields for the user will be updated.
The recommended option is to add an id field for primary key also on mapping tables or if you like me don't want to add redundant fields, you can use
UserFields::where(['user_id' => $user['user_id'], 'field_id' => 'myfield'])->update(['field_value', "new value"]);
or
DB::table('user_fields')->where(['user_id' => $user['user_id'], 'field_id' => 'myfield'])->update(['field_value', "new value"]);
Edit:
For anyone interested I did find a solution I have used before. In the model you can overload the setKeysForSaveQuery function like this
protected function setKeysForSaveQuery(Builder $query) {
$query->where('firstPKcolumn', $this->getAttribute('firstPKcolumn'))->where('otherPKcolumn', $this->getAttribute('otherPKcolumn'));
return $query;
}
Then you can use save as normal on the model
For anyone having the same issue I managed to solve this by using basic lumen db query method:
app('db')->update("UPDATE `xf_user_field_value` SET `field_value` = ? WHERE (user_id = ? AND field_id = ?);", [ $newValue, $user_id, $column ]);
I have completely disabled Eloquent as it was overkill for me and not flexible enough for my needs.

Newly created Eloquent object won't return attribute in separate create Eloquent call

The code below shows a method in my Eloquent Link class. After creating a new Link I want to create a related object LinkContact then associate() it with the new Link.
When creating LinkContact I experience an issue in accessing the Link's id attribute. The Link id value appears inaccessible only when performing the create method for the new related object (LinkContact).
Using Laravel Debugbar a line before the create method is called I've logged the Link id and I can see it just fine! Any ideas why this is happening and why I can't access the value?! Is it to do with scope?
Please take note of where the comments are
public function createActiveLink($students)
{
$links = [];
foreach ($students as $student) {
$newLink = $this->create([
'token' => $student->saudi_nid,
'status' => 'active',
'course_title' => $student->course_title,
'university_id' => $student->university_id,
'student_id' => $student->id,
'institution_id' => $student->institution_id,
'course_id' => $student->course_id,
]);
$studentContacts = $student->institutionContacts;
if ($studentContacts) {
foreach ($studentContacts as $studentContact) {
/* I get the value here, no problems */
\Debugbar::info($newLink->id);
$linkContact = $this->contacts()->create([
'type' => $studentContact->pivot->type,
'institution_contact_id' => $studentContact->pivot->institution_contact_id,
/* $newLink->id returns nothing here */
'link_id' => $newLink->id, here!!
]);
$newLink->contacts()->associate($linkContact);
$newLink->save();
}
}
$links[] = $newLink;
}
return $links;
}
The errors I receive when attempting the above code:
SQLSTATE[23000]: Integrity constraint violation: 1048
Column 'link_id' cannot be null
(SQL: insert into `link_contacts`
(`type`, `institution_contact_id`, `link_id`, `updated_at`, `created_at`)
values (1, 1, , 2015-11-24 10:26:32, 2015-11-24 10:26:32))
C:\...\vendor\laravel\framework\src\Illuminate\Database\Connection.php#631
SQLSTATE[23000]: Integrity constraint violation: 1048
Column 'link_id' cannot be null
C:\...\vendor\laravel\framework\src\Illuminate\Database\Connection.php#380
To reiterate I do get the value in Laravel Debugbar but not in the method call after it!
Edit:
In my LinkContact class link_id is in my fillable attributes:
class LinkContact extends Model
{
protected $fillable = ['type', 'link_id', 'institution_contact_id'];
// rest of the class
}
It's worth noting that:
$newLink->contacts()->associate($linkContact);
Would in this instance, run a query like:
UPDATE `link_contacts` SET `link_id` = 1 WHERE `id` = 4;
So if you're setting the link_id in the create, there's no need to run associate. If memory serves you may be able to run $newLink->contacts()->create([...]) instead of both the create() and associate().
Because of the way Eloquent works, a foreign key will always be updated/inserted from running any helper method designed to automatically insert this data but you're manually specifying the key, meaning that it's subject to $fillable so I would take a look at that, and if you don't currently have it in there, add link_id to that array.
Try
$newLink->save();
before calling
$newLink->id
The id is generated only after the data was saved in the database so there's no way of knowing it before that.

What prevents me from adding a row with foreign key value?

1452 Cannot add or update a child row: a foreign key constraint fails (`bpr`.`trips`, CONSTRAINT `trips_driver_user_id_foreign` FOREIGN KEY (`driver_user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE)
is the error.
Adding a row, manually, through MySQL works fine. If I do it through my application - nope.
The id that I am trying to insert is correct (it exists and is an integer). I checked the foreign keys and stuff, everything looks fine. I don't know what the problem might be...
Some code:
$input = Input::all();
Trip::create([
'route_from' => $input['route_from'],
'route_to' => $input['route_to'],
... adding other stuff ...
'driver_user_id' => Auth::user()->id
]);
When I var_dump(Auth::user()->id) I do get correct int number, which is the correctly corresponding ID of the certain user.
in the Trip model:
protected $hidden = [
'id'
];
protected $fillable = [
'route_from',
'route_to',
...
'driver_user_id'
];
public function Trip()
{
return $this->belongsTo('User', 'driver_user_id', 'id');
}
in the User model:
public function Trips()
{
return $this->hasMany('Trip');
}
I have the gut feeling the attributes are guarded. Your code seems correct, however the error you receive originates from the database. Could you try it like this and see if it works:
$trip = new Trip;
$trip->unguard();
$trip->fill([
'route_from' => $input['route_from'],
'route_to' => $input['route_to'],
... adding other stuff ...
'driver_user_id' => Auth::user()->id
]);
$trip->save();
Using the create method on the model makes it difficult to debug what is happening.

CakePHP: Duplicate entry for key "PRIMARY' for shell script

I am creating a real estate website that has Listing ID's attached to each listing. I am running a script via shell in CakePHP that is parsing a csv file and should be updating any listing that already exists or inserting a new one if it does not.
The problem is that I keep getting a Duplicate entry '###' for key "PRIMARY' where ### is the Listing ID that is being provided by the CSV. This script is being run from the command line.
Here's a smaller version of what my table includes:
CREATE TABLE `listings` (
`ListingID` int(11) NOT NULL,
`AccessibilityYN` varchar(50) DEFAULT NULL COMMENT 'AccessibilityYN',
`BathsFull` int(6) DEFAULT NULL COMMENT 'BathsFull',
`BathsPartial` int(6) DEFAULT NULL COMMENT 'BathsPartial',
`BathsTotal` decimal(5,1) DEFAULT NULL COMMENT 'BathsTotal',
`Beds` int(11) DEFAULT NULL COMMENT 'Beds',
PRIMARY KEY (`ListingID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Here's my Listing Model (notice that I have public $primaryKey = 'ListingID';)
class Listing extends AppModel {
public $name = 'Listing';
public $primaryKey = 'ListingID';
public $belongsTo = array(
'Agent' => array(
'className' => 'Agent',
'foreignKey' => 'AgentID'
)
);
}
Here's the shell I'm running via command line:
class MyShell extends AppShell {
public $uses = array('Listing');
public function update_imported_listings() {
/***SOME CODE HERE TO GET THE $entry FROM THE CSV***/
$this->Listing->ListingID = $entry['ListingID'];
if(!$this->Listing->exists()){
$this->Listing->create();
}
if($this->Listing->save($entry)){
echo "Saved Listing";
} else {
echo "Listing Failed";
}
}
}
I understand that CakePHP usually likes id to be the field used in the database, however I have set $primaryKey = 'ListingID' in my model. I've tried setting ListingID to Auto Increment in the DB but that didn't work.
Anybody have any ideas? I'm fresh out.
Setting ListingID doesnt' do anything
This line is your problem:
$this->Listing->ListingID = $entry['ListingID'];.
Irrespective of what your actual primary key field is in database the primary key value is always specified using Model->id property. As such, change it to:
$this->Listing->id = $entry['ListingID'];
You don't need to call exists
There is not need to explicitly check if record with particular primary key values exists. Cake will automatically update and record instead of creating a new one if the data array passed to save() contains a valid primary key value which exists in db. Just ensure you call create() before saving if you are using save() in a loop.
Don't break CakePHP conventions, use 'id' field as primary key.
http://book.cakephp.org/view/24/Model-and-Database-Conventions
I was getting the same error running a cakePHP shell script, turns out the latest record's ID was at the maximum value allowed by the size of the column (whoever made the table used a medium int for the id column), so auto_increment wasn't working. Changed the column to allow for larger numbers to fix. Probably something obvious, but might help someone out there.

Categories