Can't delete a collection of Laravel eloquent - mysql

I am retrieving a collection from db and want to delete it. This is the code.
$signal_id = $request->del_signal_id;
$signal_details = VwDistressSignals::where('signal_id', $signal_id)->delete();
return "Success";
}
And this is the error.
message: "SQLSTATE[HY000]: General error: 1395 Can not delete from join view 'dvp.vw_distresssignals' (SQL: delete from `vw_distresssignals` where `signal_id` = 2)"
I have also tried giving all the column names. This is the model...
<?php
namespace App\Models;
use Reliese\Database\Eloquent\Model as Eloquent;
class VwDistressSignals extends Eloquent
{
protected $table = 'vw_distresssignals';
}

This error is happening because your relationship is not properly defined.

Delete with the loop
$signal_id = $request->del_signal_id;
$signal_details = VwDistressSignals::where('signal_id', $signal_id)->get();
foreach($signal_details as $detail)
{
$detail->delete();
}
return "Success";

Since you haven't shared your model, I assume it corresponds to a database view rather than a table.
If so try deleting from the base table(s) as join views are not deletable.
DELETE ... Join views are not allowed.
https://dev.mysql.com/doc/refman/5.7/en/view-updatability.html

Related

database relation between two different server

I have two servers and both of them contain several tables. Many of them contain relations. Now I need to join those tables and fetch data. I have no clue how to write this sort of query. Currently, I'm working in Laravel. Any suggestions will help me.
Thanks in advance.
If you want to use model relationships you can add connection and table field in your model;
class User extends Model {
public $connection = 'firstconnection';
public $table = 'users';
...
public function comments() {
return $this->hasMany(Comment::class);
}
}
class Comment extends Model {
public $connection = 'secondconnection';
public $table = 'comments';
...
}
You can define connections in your config/database.php, default connection is mysql.
If you write raw queries you can use full table path (specify database):
SELECT * FROM db1.users JOIN db2.comments ON db1.users.id = db2.comments.user_id;
Note: you must have enough privileges on both tables to join and select data. If you use exists, has or semething like that where ORM needs to join two table.
Hope this helps you

How to write this raw query using query builder? Is my one correct?

This is the expected result of raw query
$sql = 'SELECT c.*
FROM catalogs c
LEFT JOIN (SELECT s.* FROM stock s WHERE s.date = "'.$dateOption.'") as sb
on sb.id_product = c.id_product
WHERE c.id_branch = '.Auth::user()->id_branch.';
$list = DB::select($sql);
I modified it using query builder, but the result is not correct
$lists = DB::table('catalogs')
->leftJoin('stock', 's.id_product','=','catalogs.id_product')
->where('s.date',$dateOption)
->where('catalogs.id_branch',Auth::user()->id_branch)
->get();
Anyone can tell me how should i write it in query builder?
Defining Relationships (more details)
The first argument passed to the hasOne method is the name of the related model. Once the relationship is defined, we may retrieve the related record using Eloquent's dynamic properties. Dynamic properties allow you to access relationship methods as if they were properties defined on the model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
And then you can get the join like bellow.
$phone = User::find(1)->phone;

Yii2 ActiveQuery disambiguation

I have a policy table and a policy_chapter table. I want to modify my PolicyQuery so that it will only display policies from chapters that belong to that client. Here's my code inside PolicyQuery which extends ActiveQuery:
public function one($db = null)
{
if (Yii::$app->user->can('Admin')) return parent::one($db);
if (Yii::$app->user->can('PolicyUser')) {
$this->joinWith('chapter')->andWhere(['policy_chapter.client_id'=>Yii::$app->user->identity->client_id]);
return parent::one($db);
}
}
If the user has Admin access then he can look at any policy. If he has PolicyUser access, then it will make sure he can't get to a policy in another client's chapters. But I get this error:
SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous The SQL being executed was: SELECT policy.* FROM policy LEFT JOIN policy_chapter ON policy.chapter_id = policy_chapter.id WHERE (id='280') AND (policy_chapter.client_id=1)
It fails because it is search on id and both the policy and the policy_chapter table have an id field. I cannot figure out how to disambiguate the id.
I solved this by changing the findModel method in the policy controller. I replaced the Policy::findOne($id) call with Policy::find()->where('policy.id = :id',[':id'=>$id])->one()
That disambiguated the policy id.
modify your query to this:
public function one($db = null)
{
if (Yii::$app->user->can('Admin')) return parent::one($db);
if (Yii::$app->user->can('PolicyUser')) {
$this->joinWith('chapter as cha')->alias('t')->andWhere(['policy_chapter.client_id'=>Yii::$app->user->identity->client_id]);
return parent::one($db);
}
}
then you can use cha.id reference to policy_chapter table and t.id reference to policy table.
Try with:
public function one($db = null)
{
if (Yii::$app->user->can('Admin')) return parent::one($db);
if (Yii::$app->user->can('PolicyUser')) {
$sql = $this->joinWith('chapter')->andWhere(['policy_chapter.client_id'=>Yii::$app->user->identity->client_id])->andWhere(['policy.id' => $this->id])->createCommand()->getRawSql();
$model = Policy::findBySql($sql)->one();
return $model;
}
}

Use a column value in an other table with laravel query builder

I have two table witch named users & Inbox
In the Inbox table I have a column named sender_id that have the user_id of the sender
I want to show this message in the view. I need a query to get the sender_id from the inbox table and use that to select a certain user from the users table
I need to do this with all messages and all users.
Laravel is basicly straith foward when you use eloquent. You can always customise it.
First, almost all the time, I create a model and a migration at the same time using this : php artisan make:model Something --migration
I know you already make some models and/or migrations, but I'll go step by step to help you understand it.
So, in your case, it'll be php artisan make:model User --migration and php artisan make:model Inbox --migration. Doing this, you get two model named User and Inbox and two migration named date_create_users_table.php and date_create_inboxs_table.php. Maybe you already did the default user table with php artisan make:auth. If it's the case, don't remake one.
I'm not sure about how laravel will name the Inbox model migration... Since, I think, Laravel 5.3, the plurialisation changed and don't always just add an "S" at the end.
Then, now you got your models and migrations, let's add some line into your migration files. Since you want to do a one to many relationship. You don't need to touch the user one. Only the Inbox migration. Each Inbox is related to one User and Users can have many Inboxs. Add something like this in your migration:
public function up()
{
Schema::create('inboxs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->foreign('user_id')->references('id')->on('users');
all other columns...
});
}
There, you can change the column's name if you need to have a sender, a recipient, etc... Do this instead :
public function up()
{
Schema::create('inboxs', function (Blueprint $table) {
$table->increments('id');
$table->integer('sender_id');
$table->foreign('sender_id')->references('id')->on('users');
$table->integer('recipient_id');
$table->foreign('recipient_id')->references('id')->on('users');
all other columns...
});
}
What we just did, it's creating the Foreign key that Laravel will use to build the query. There is one last part before the fun one. We need to create the relation in our Model. Begin with the user one:
App/User.php
public function inboxs() {
return $this->hasMany(Inbox::class);
}
And now into the App/Inbox.php model:
public function user() {
return $this->belongsTo(User::class);
}
If you need to have a Sender/Recipient/etc... go this way instead:
public function sender() {
return $this->belongsTo(User::class);
}
public function recipient() {
return $this->belongsTo(User::class);
}
Note that each of your function need to be writen in the same way it's into your migration. sender_id need a relation named sender().
Now, that our relations are done, we can simply call everything using eloquent.
$inboxs = Inbox::with('sender')->get();
This will return an array of all your Inbox into the inboxs table. You can access the sender this way: $inboxs[0]->sender();
You need the id, do this: $sender_id = $inboxs[0]->sender_id;
The sender name : $sender_name = $inboxs[0]->sender->name;
If you want to get one Inbox and you have the id, just do this $inbox = Inbox::with('sender')->find($id);
This way you don't get an array, only one result and can access the sender directly using $sender_name = $inbox->sender->name; instead of having to add [0] or using a foreach loop.
You can get all messages sended by a user using something like this:
$inboxs = Inbox::where('sender_id', $sender_id)->get();
Finally, you can pass your data to the view using:
return view('path.to.view')->with('inbox',$inbox);
Into the view you do this to show the sender's name:
//If view.blade.php
{{$inbox['sender']['name']}} //work a 100%
{{$inbox->sender->name}} //I'm not sure about this one
//If not using blade
<?php echo $inbox['sender']['name']; ?>
There is a lot of thing you can do using Eloquent and you can add as much condition you want. The only thing I suggest you to really do if you want to use Eloquent, be aware about the n+1 problem. There is a link where I explain it. Look for the EDIT section of my answer.
If you need some documentation:
Laravel 5.3 Relationships
Laravel 5.3 Migrations
Laravel 5.3 Eloquent
I think you should update your code like:
$user_messages = DB::table('messages')
->select('messages.id as msgId','messages.message as message','users.id as userId','users.user_name as user_name')
->join('messages','messages.user_id','=','users.id')
->where('messages.user_id',$user_id)
->get();
return view("view.path")
->with('messages',$user_messages);
Hope this work for you!
In Model :
namespace App;
use Illuminate\Database\Eloquent\Model;
class Messages extends Model
{
protected $table = 'table_name';
public function sender()
{
return $this->belongsTo('App\User', 'sender_id', 'id');
}
}
In Controller :
public function functionName($user_id){
$messages = Messages::where('sender_id', $user_id)->get();
return view("view.path")
->with('messages',$messages);
}
In view, you can access seder details like this $message->sender->name for name for id $message->sender->id

Error in setting up laravel Eloquent relationship

I am trying to set up a relationship in Laravel using the eloquent relationship model, it looks like the one below
users
id
email
projects
id
name
user_projects
user_id
project_id
role
I want to be able to query the projects that the user is a part of irrespective of the role that he has. To do this, I used the following in my user model.
class User extends Model {
public function allProjects() {
return $this->belongsToMany('App\ProjectRoles', 'user_projects', 'user_id', 'project_id');
}
}
But because of this I get an error in my code
Syntax error or access violation: 1066 Not unique table/alias: 'user_projects' (SQL: select `user_projects`.*, `user_projects`.`user_id` as `pivot_user_id`, `user_projects`.`project_id` as `pivot_project_id` from `user_projects` inner join `user_projects` on `user_projects`.`id` = `user_projects`.`project_id` where `user_projects`.`user_id` = 2)
I am not sure how to create the join query in the relationships in order to do it. Any help would be appreciated. I went through the eloquent docs but wasn't able to get the result even though the examples there do exactly what I want.
Your belongsToMany relationship is related to the wrong Model. Generally you don't have a model for your pivot table, but even if you do, your belongsToMany relationship doesn't use it. Your User model should be related to your Project model.
You should use this:
class User extends Model {
public function allProjects() {
return $this->belongsToMany('App\Project', 'user_projects', 'user_id', 'project_id');
}
}