Trying to update attribute result in mass-update [Laravel 5] - php

I'm trying to change a value in my DB for a single item, I use first() to get an item, but for some reason when I try this function, every entry with the same primary key has the authenticated user gets the attribute 'AreFriend' updated at 1, why?
public function acceptrequest($id)
{
$user = app('Dingo\Api\Auth\Auth')->user();
if (!$targetuser = User::find($id)) {
return response()->json(['status' => "The requested resource does not exists!"], 403);
}
if ($relation = $user->requestspending()->where('user_id', $targetuser->user_id)->first()) {
Friend::unguard();
$relation->AreFriend = 1;
$relation->save();
Friend::unguard();
Friend::reguard();
return response()->json(['status' => "Request accepted!"], 200);
} else {
return response()->json(['status' => "You do not have an invitation from this user!"], 403);
}
}
In my database, relations with the $user id are updated. The variable $relation is an item, not a collection.

Related

Unable to retrieve a one to one polymorphic relationship

I have a pretty complex Laravel application who creates a one to one polymorphic relationship in a middleware if it does not exists. The fact is that I am unable to retrieve the relationship in the same request (create in middleware, then pass it and retrieve it), I have an error 500 when I try to do this. BUT, if I a make an other request I can retrieve it... When I look into my database, I have the userable_id and type defined, I have no idea where this can probably occur.
My middleware look like this:
public function handle(Request $request, Closure $next): mixed
{
if (!Storage::disk('cecurity')->exists(config('coffre_fort.ssl_certificate.name')) ||
!config('coffre_fort.reverse_proxy.username') ||
!config('coffre_fort.reverse_proxy.password') ||
!config('coffre_fort.encryption_key')) {
return response()->json([
'error' => 'Cecurity is not configured correctly.',
], 500);
} elseif (!Auth::user()) {
return response()->json([
'error' => 'You are not authenticated.',
], 401);
}
if (!Auth::user()->cecurityAccount) {
try {
$userType = Auth::user()::class;
/** #phpstan-ignore-next-line */
if ($userType == "App\Models\Admin") {
$this->cecurityRepository->createAdminUser(Auth::user());
} else {
// It enter in this function for creating relationship
$this->cecurityRepository->createFullCustomer(Auth::user());
}
} catch (Exception $e) {
return response()->json([
'error' => $e->getMessage(),
], 500);
}
} elseif (!$this->cecurityRepository->checkConnection()) {
$this->cecurityRepository->connect(
Auth::user()->cecurityAccount->cecurity_user_id,
openssl_decrypt(
Auth::user()->cecurityAccount->password,
'AES-256-CBC',
config('coffre_fort.encryption_key'),
0,
(int) Auth::user()->cecurityAccount->encryption_iv
),
Auth::user()->cecurityAccount->coffre_id
);
}
return $next($request);
}
Then it creates the relationship as this (in the createFulCustomer() function):
$user = new Cecurity;
$user->userable_id = $customer->id_customer;
$user->userable_type = Customer::class;
And then pass the middleware to go to listFiles() function in a controller:
public function listFiles(ListFilesRequest $request): mixed
{
try {
return $this->cecurityRepository->listFiles(
$request->get('nbRowByPage'),
$request->get('pageIndex'),
);
} catch (\Exception $e) {
return response()->json([
'message' => $e->getMessage()
], 500);
}
}
Just after the middleware has passed, my database is completed (Cecurity table related):

Laravel Property does not exist on this collection instance

I need to transfer data from Mysq table (Paniers) to another Mysql table (Commandes) and delete the data from first table after transfer.
Here is my code:
function Commande(Request $request) {
$pn = $request->input('id');
$pdr = Panier::find($pn);
$user = Commande::create([
'ID_User' => $pdr->ID_User,
'ID_Piece' => $pdr->ID_Piece,
'QTE' => $pdr->QTE,
]);
if($user){
if($pdr->delete())
{
echo 'Commande Confirmée';
}
}
}
I get this error:
"Property [ID_User] does not exist on this collection instance."
If i do this it works but instead of getting all data i only get the first line. I need to get all lines of data!
$pdr = Panier::find($pn)->first();
If $pn is array Panier::find($pn) returns collection not entity so you should iterate it
Panier::find($pn)->each(function($pdr){
$user = Commande::create([
'ID_User' => $pdr->ID_User,
'ID_Piece' => $pdr->ID_Piece,
'QTE' => $pdr->QTE,
]);
if($user){
if($pdr->delete())
{
echo 'Commande Confirmée';
}
}
});
When you are doing :
$pdr = Panier::find($pn);
If the record does not exist, it will return null. Then if you do $pdr->ID_User it is going to throw an error. Please check beloew updates :
<?php
function Commande(Request $request) {
$pn = $request->input('id');
$pdr = Panier::find($pn);
// Model not found
if(!$pdr){
return response()->json(['msg' => 'No records found']);
}
// Create new Commande
$user = Commande::create([
'ID_User' => $pdr->ID_User ?? 'default_value_for_ID_User',
'ID_Piece' => $pdr->ID_Piece ?? 'default_value_for_ID_Piece',
'QTE' => $pdr->QTE ?? 'default_value_for_QTE'
]);
// If user is created
if($user){
// Delete Panier
$pdr->delete();
return response()->json(['msg' => 'Success']);
}
return response()->json(['msg' => 'Could not create new Commande']);
}
For above to work you need to have :
Columns ID_User, ID_Piece and QTE marked as $fillable = [] in Commande Model.
You need to have a basic primary key for Panier Model, otherwise delete() will not work.
You can do it by findOrFail and handling Exception:
function Commande(Request $request) {
$pn = (int) $request->input('id');
try {
$pdr = Panier::findOrFail($pn);
$pdr->each(function ($item, $key) {
$user = Commande::create([
'ID_User' => $item->ID_User,
'ID_Piece' => $item->ID_Piece,
'QTE' => $item->QTE,
]);
if ($user && $item->delete()) {
echo 'Commande Confirmée';
}
});
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e) {
//#Todo handle error
}
}
According to laravel 5.0 documents:
Retrieving A Model By Primary Key Or Throw An Exception
Sometimes you may wish to throw an exception if a model is not found. To do this, you may use the firstOrFail method:
Collection

Update record in laravel shows not exist message ( Not Updating Record )

I have two separate APIs calls. One for click on edit page and another for update page:
The controller method when the user hits edit link:
public function EditList($page_id)
{
$listEdit= DB::table('page_master')->where('id',$page_id)->first();
return view('edit-list',compact('listEdit'));
}
and its route:
$router->get('/edit-List/{id}', 'AjaxController#EditList');
The above code successfully shows me the edit page where I will perform the update.
My next step is update record:
The controller method
public function updatePage($id)
{
$updatePage = $this->page->updatePage($id);
if(!$updatePage)
{
$resultArray = ['status' => 0, 'message' => 'Page not exist!'];
return Response::json( $resultArray, 400);
}
else{
$resultArray = ['status' => 1, 'message' => 'Page updated !'];
return Response::json($resultArray, 200);
}
}
and its routes:
Route::post('update/list/{id}',['uses' => 'ApiController#updatePage']);
Now when i click on update record it shows me the page does not exist even though the page is there in database but always showing the page does not exist page.
What should I change to make the routes work properly?
public function updatePage($id)
{
$updatePage = self::find($id);
if (is_null($updatePage)) {
return false;
}
$input = Input::all();
$updatePage->fill($input);
$updatePage->save();
return $updatePage;
}

How to set multi select value from array object in yii2 while updating

I have table which have multiple reference to ohter tables like
user
id name email
categories
id title
user_categories
user_id category_id
Here a user will have multiple category associated with him/her
I am able to save these successfully with new records like following
View File:
echo $form->field($package_categories, 'category_id')->dropDownList( ArrayHelper::map(
StudyMaterialCategories::find()->all(), 'id', 'title'),
['multiple' => true]
);
Save New record:
$model = new Packages();
$package_categories = new PackageCategories();
$request = Yii::$app->request;
if ($request->isPost) {
$transaction = Yii::$app->db->beginTransaction();
try {
$post = $request->post();
$model->load($post);
$model->save();
foreach ($post['PackageCategories']['category_id'] as $key => $value) {
$package_categories = new PackageCategories();
$package_categories->category_id = $value;
$package_categories->package_id = $model->id;
$package_categories->save();
}
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
} catch (Exception $ex) {
$transaction->rolback();
Yii::$app->session->setFlash("error", $ex->getMessage());
}
}
Till now It's running successfully.
But I'm stuck when going to update the table. The problem part is dropdown list. How to set multiple selected option as per database if I'm coming with array of object.
Have a look on the following code
$package_categories = PackageCategories::find()
->where('package_id=:package_id', ['package_id' => $id])->all();
if (count($package_categories) < 1) {
$package_categories = new PackageCategories();
}
$request = Yii::$app->request;
if ($request->isPost) {
$transaction = Yii::$app->db->beginTransaction();
try {
$post = $request->post();
$model->load($post);
$model->save();
$package_categories = new PackageCategories();
$package_categories->deleteAll(
"package_id=:package_id",
[':package_id' => $model->id]
);
foreach ($post['PackageCategories']['category_id'] as $key => $value) {
$package_categories = new PackageCategories();
$package_categories->category_id = $value;
$package_categories->package_id = $model->id;
$package_categories->save();
}
$transaction->commit();
return $this->redirect(['view', 'id' => $model->id]);
} catch (Exception $ex) {
$transaction->rolback();
Yii::$app->session->setFlash("error", $ex->getMessage());
}
}
if I try to get first object of the array $package_categories of only able to set selected one option
This is an example code of a model class Permit which has a many to many relationship with Activity through PermitActivity (pivot table model).
Model Class Activity
public class Permit extends \yii\db\ActiveRecord {
public $activities_ids;
...
public function rules() {
return [
...
[['activities_ids'], 'safe'],
...
];
}
...
// Method called after record is saved, be it insert or update.
public function afterSave($insert, $changedAttributes) {
// If this is not a new record, unlink all records related through relationship 'activities'
if(!$this->isNewRecord) {
// We unlink all related records from the 'activities' relationship.
$this->unlinkAll('activities', true);
// NOTE: because this is a many to many relationship, we send 'true' as second parameter
// so the records in the pivot table are deleted. However on a one to many relationship
// if we send true, this method will delete the records on the related table. Because of this,
// send false on one to many relationships if you don't want the related records deleted.
}
foreach($this->activities_ids as $activity_id) {
// Find and link every model from the array of ids we got from the user.
$activity = Activity::findOne($activity_id);
$this->link('activities', $activity);
}
parent::afterSave($insert, $changedAttributes);
}
...
// Declare relationship with Activity through the pivot table permitActivity
public function getActivities(){
return $this->hasMany(Activitiy::className(), ['id' => 'activity_id'])
->viaTable('permitActivity',['permit_id' => 'id']);
}
...
public function afterFind(){
parent::afterFind();
$this->activities_id = ArrayHelper::getColumn($this->activities, 'id');
}
}
This way the model class is the one responsible for creating and updating the relationship using the pivot table.
The most important thing is to have the relationship method declared correctly.
Edit
This is an example of the view using kartikv\widgets\Select2. I don't really know if dropDownList supports multiple select, however Select2 has so many useful features i usually use it over other options.
echo $form->field($model, 'activities')->widget(Select2::classname(), [
'data' => $data,
'options' => [
'placeholder' => '...'
],
'pluginOptions' => [
'allowClear' => true,
'multiple' => true,
],
]);

Check if laravel model got saved or query got executed

I've seen alot of people using this way to check if a laravel model got saved. So now I wonder if it is a safe way.
And also can I check if the queries bellow got executed like this
Check if model got saved
Eg:
$myModel = new User();
$myModel->firstname = Input::get('firstname');
$myModel->lastname = Input::get('lastname');
$myModel->save();
//Check if user got saved
if ( ! $myModel->save())
{
App::abort(500, 'Error');
}
//User got saved show OK message
return Response::json(array('success' => true, 'user_added' => 1), 200);
Is the above a safe way to check whenever my model got saved or not?
Check if query returned a result
Eg:
$UserProduct = Product::where('seller_id', '=', $userId)->first();
if (! $UserProduct)
{
App::abort(401); //Error
}
Does above return an error if no product where found?
Check if query got executed
Eg:
$newUser = User::create([
'username' => Input::get('username'),
'email' => Input::get('email')
]);
//Check if user was created
if ( ! $newUser)
{
App::abort(500, 'Some Error');
}
//User was created show OK message
return Response::json(array('success' => true, 'user_created' => 1), 200);
Does above check if a user was created?
Check if model got saved
save() will return a boolean, saved or not saved. So you can either do:
$saved = $myModel->save();
if(!$saved){
App::abort(500, 'Error');
}
Or directly save in the if:
if(!$myModel->save()){
App::abort(500, 'Error');
}
Note that it doesn't make sense to call save() two times in a row like in your example. And by the way, many errors or problems that would keep the model from being saved will throw an exception anyways...
Check if query returned a result
first() will return null when no record is found so your check works find. However as alternative you could also use firstOrFail() which will automatically throw a ModelNotFoundException when nothing is found:
$UserProduct = Product::where('seller_id', '=', $userId)->firstOrFail();
(The same is true for find() and findOrFail())
Check if query got executed
Unfortunately with create it's not that easy. Here's the source:
public static function create(array $attributes)
{
$model = new static($attributes);
$model->save();
return $model;
}
As you can see it will create a new instance of the model with the $attributes and then call save(). Now if save() where to return true you wouldn't know because you'd get a model instance anyways. What you could do for example is check for the models id (since that's only available after the record is saved and the newly created id is returned)
if(!$newUser->id){
App::abort(500, 'Some Error');
}
You can also check the public attribute $exists on your model.
if ($myModel->exists) {
// Model exists in the database
}
I would do such move to when I use Model::create method :
$activity = Activity::create($data);
if ($activity->exists) {
// success
} else {
// failure
}
As for the Save method it's easier because $model->save() returns Bool :
$category = new Category();
$category->category_name = $request->category_name;
$is_saved = $category->save();
if ($is_saved) {
// success
} else {
// failure
}
/**
* Store a newly created country in storage.
*
* #url /country
* #method POST
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function store(Request $request)
{
# Filer & only get specific parameters.
$request = $request->only('code', 'name', 'status');
# Assign login user(Auth Control).
$request['created_by'] = Auth::user()->id;
# Insert data into `countries` table.
$country = Country::create($request);
if(!$country)
throw new Exception('Error in saving data.');
}

Categories