In the admin panel, I have something called Group that an admin can make a group of users so my scheme is:
groups table contains:
id
name
1
group1
group_user table contains:
id
group_id
user_id
1
1
2
2
1
3
My logic is: if a user belongs to a group, that user cannot be added again to the same group:
In update, when I add a user that already exists in group, it added it again:
public function update($id, Request $request)
{
$request->validate([
'name' => 'sometimes|nullable|string',
'user_ids' => 'sometimes|array',
]);
$group = Group::findOrFail($id);
$group->update($request->only('name'));
if ($ids = $request->user_ids) {
$group->users()->attach($ids);
}
return $this->apiRespone(null, 'group updated successfully', null, 200);
}
Just check if user already is in the group before attaching to it:
public function update($id, Request $request)
{
$request->validate([
'name' => 'sometimes|nullable|string',
'user_ids' => 'sometimes|array',
]);
$group = Group::findOrFail($id);
$group->update($request->only('name'));
foreach($request->user_ids as $user_id) {
if (!$group->users()->where('id', $user_id)->exists()) {
$group->users()->attach($user_id);
}
}
return $this->apiRespone(null, 'group updated successfully', null, 200);
}
Update:
To get the list of already existing members, apply this in your loop logic:
$existingUsers = [];
foreach($request->user_ids as $user_id) {
if (!$group->users()->where('id', $user_id)->exists()) {
$group->users()->attach($user_id);
} else {
$existingUsers[] = $user_id;
}
}
// now you can use $existingUsers
Related
I'm currently working on a project that has an accounts management section where the system admin creates the user accounts.
The [Users] table has a column named "Organization_name", which is the user's represented organization. After submitting the form, "Organization_name" will then be also added to the [Organization] table, under the [name] field. The two tables are related by the "user_id" column (taken from the "id" column of the [Users]).
I managed to create a working code to add a [Users] account that also adds the organization_name to the [Organization] table, although now I'm wondering how can I make a function that will also edit the rows in the [Organization] table whenever I edit the fields in [User].
(ex. I changed the "organization_name" field in [Users] with id=1 from "Organization A" to "Organization B," the "name" field in [Organization] with user_id=1 should also change from "Organization A" to "Organization B" too).
NOTE: "role_id" determines what kind of account permissions a user account will have, it doesn't affect the question but I'll leave it in the code snippet below just in case.
I'll attach the codes that I used below:
UserController.php
private static function createUser(Request $request)
{
$user = new User();
$user->email = $request->get('email');
$user->organization_name = $request->get('organization_name');
$user->password = Hash::make($request->get('password'));
$user->role_id = $request->get('role_id');
return $user;
}
private static function createSubUser(Request $request, $user_id)
{
$role_id = $request->get('role_id');
if($role_id == 1)
{
$sub_user = new Organization();
$sub_user->user_id = $user_id;
$sub_user->name = $request->get('organization_name');
}
elseif($role_id == 2)
{
$sub_user = new Staff();
$sub_user->user_id = $user_id;
}
elseif($role_id == 3)
{
$sub_user = new Administrator();
$sub_user->user_id = $user_id;
}
return $sub_user;
}
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'email' => 'required|string|email|max:255|unique:users',
'organization_name' => 'required|string|max:255|unique:users',
'password' => 'required|string|min:6',
]);
if($validator->fails()){
return response()->json($validator->errors()->toJson(), 400);
}
$user = static::createUser($request);
$user->save();
$sub_user = static::createSubUser($request, $user->id);
$sub_user->save();
}
public function updateUserInfo(Request $request)
{
$user = User::find($request->id);
if($user->email == $request->email){
$check_email = false;
}
else{
$check_user = User::where('email', $request->email)->first();
if (!empty($check_user)) {
$check_email = true;
}
else {
$check_email = false;
}
}
if($check_email === true)
{
return response()->json([
'success' => false,
'error' => "User with the registered email of {$request->input('email')} already exists",
]);
}
else
{
$user = User::where('id', $request->id)->update([
'email' => $request->input('email'),
'organization_name' => $request->input('organization_name'),
'role_id' => $request->input('role_id')
]);
return response()->json([
'success' => true,
'user' => $user
]);
}
}
Thank you!
Why you need to add user_id on organization??
An organzation should have many students or users.No need to store organization_name on users table just save the id of organization.When you need to update organization name just update it on organization table.Because you don't need to change in user table you just save here id. Feel free to comment if you have any confussion.
I'm working on laravel 5.4 and I have this code:
public function apply($id){
$user = User::where('id', $id)->get()->first();
$data = [
'name' => $user->first_name,
'family' => $user->last_name,
'email' => $user->email,
'username' => $user->username,
'gender' => $user->gender,
'birthday' => $user->birthday,
'cv' => $user->cv,
'about' => $user->about,
'education' => $user->education,
'experiences' => $user->experiences,
];
$company = Company::get()->first();
Mail::send('emails.apply', $data, function ($message) use ($company)
{
$message->from('noreply#gmail.com', 'Robert Nicjoo');
$message->subject('New Apply');
$message->to($company->email);
});
Mail::send('emails.uapply', $data, function ($message) use ($user)
{
$message->from('noreply#gmail.com', 'Robert Nicjoo');
$message->subject('You Applied successfully');
$message->to($user->email);
});
Session::flash('success', 'Your application was sent to company.');
return redirect()->back()->with('session', $data);
}
This will send email to company when user click on apply button and send user info to them, now I also want to save data of the user include user_id, ad_id and company_id in another table so both user and company owners can have access to their history of applied ads.
I also have this table to save data on:
public function up()
{
Schema::create('applies', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('ad_id')->unsigned();
$table->integer('company_id')->unsigned();
$table->timestamps();
});
Schema::table('ads', function($table) {
$table->foreign('user_id')->references('id')->on('users');
$table->foreign('ad_id')->references('id')->on('ads');
$table->foreign('company_id')->references('company_id')->on('ads');
});
}
but in my controller (first codes) I need to know how to save those information in new table (second codes)?
Update:
Ad Model >>
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Ad extends Model
{
protected $fillable = [
'company_id', 'title', 'slug', 'image', 'description', 'address', 'job_title', 'salary',
];
public function company(){
return $this->belongsTo(Company::class);
}
public function category(){
return $this->belongsTo(Category::class);
}
public function location(){
return $this->belongsTo(Location::class);
}
public function employment(){
return $this->belongsTo(Employment::class);
}
}
since your blade is like this:
<a class="btn btn-info btn-round" href="{{ route('apply.btn', Auth::user()->id) }}">
your route should look like
Route::get('apply/{id}', 'ApplyController#apply')->name('apply.btn');
why id only ? because in the discussion we had, i found out that ad_id and company_id was taken from the controller .. then in your controller this should work
public function apply($id)
{
$ad = Ad::first();
$company = Company::first();
$apply = new Apply();
$apply->user_id = $id
$apply->ad_id = $ad->id;
$apply->company_id = $company->id;
$apply->save();
// some more codes //
}
to avoid duplicates using user_id .. add a validation function like
function validateApply(array $data)
{
return Validator::make($data, [
'user_id' => 'required|numeric|unique:apply,user_id,NULL,id,ad_id,'.$data->ad_id,
]);
}
unique:apply - it means it will check the apply table the user_id already applied ..
then in the code above just do
$validateApply= $this->validateApply(['user_id'=>$id,'ad_id'=>$ad->id]);
if(!$validateApply->fails())
{
// do the above code here
}
else
{
// duplicate !!! so do your code here
}
then to retrieve the data assuming apply is already belongsTo the user as well the user hasOne apply
Auth::user()->apply->first()->somefield;
// im not sure how the hasOne works but try
Auth::user()->apply->somefield;
Your Route should be:
Route::post('apply/{$user_id}/{company_id}/{ad_id}','ApplyController#apply');
I think you have created model for ads.
So, simply save data like this:
Your function be like
public function apply(Request $request){
// other code
$apply = new Apply();
$apply->user_id = $request->user_id;
$apply->ad_id = $request->ad_id;
$apply->company_id = $request->company_id;
$apply->save();
// other code
}
And one more thing, You should have ad_id in your post request.
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,
],
]);
order_id....product_id....product_quantity....created_at....updated_at
this is my pivot table...In my OrderRequest table I want to assign product_id as unique. But when I write like this;
public function rules()
{
return [
'product_id' => 'unique:order_product,product_id'
];
}
I encounter a problem. product_id becomes unique. but not only in an order, it becomes totally unique. I want to use this product_id in other orders but I can't. what can I do? How can I assign product_id as unique for each order_id values?
In your controller assuming that you call saveProducts method so :
function saveProducts($request){
validateProductList($request->input('product_list'))
$order->product()
->updateExistingPivot($product_id[$i],
array(
'product_quantity' => $product_quantity[$i],
'product_status' => $product_status[$i],
'updated_at' => Carbon::now() ));
// ....
}
function validateProductList($productIds){
if(isProductIdDuplicated($productIds)){
$error = 'You have a duplicated product in your Order, please edit it'
return redirectBack()-withError();
}
}
function isProductIdDuplicated($productIds){
$occureces_array = productIds();
foreach($productIds as $id){
if(++$occureces_array[$id] > 1){
return true;
}
}
return false;
}
And in your view you have access to this $error variable.
Thank you for your help. I have ended up the issue and it works now...
this is a part of my view;
<div class="grid1">
{!! Form::label('product_list'.$product_row, Lang::get('home.Select Product')) !!}
</div>
<div class="grid2 searchDrop">
{!! Form::select('product_list[]', $product_list, null, ['style'=>'width:150px;'])!!}
and this is part of my controller;
public function store(OrderRequest $request)
{
$order = Order::create( $request->all());
$product_list= $request->input('product_list');
$product_quantity = $request->input('product_quantity');
$product_status = $request->input('product_status' );
/* attach pivot table */
$order->product()->attach($product_list);
/* get the product list as array */
foreach($product_list as $key => $product_id)
{
$order->product()->updateExistingPivot($product_id, array(
'product_quantity' => $product_quantity[$key], // product_quantity is array
'product_status' => $product_status[$key], // product_status is array
'updated_at' => Carbon::now()
));
}
flash(Lang::get('home.The order has been created!'));
return redirect(url('/admin/orders/details',$order->id))->with('flash_message');
}
this is my OrderRequest;
public function rules()
{
return [
'customer_id' => 'required',
'product_quantity.*' =>'not_in:0',
'product_list' => 'product_unique', //custom validation in AppServiceProvider
];
}
and this is my AppServiceProvider;
public function boot()
{
Validator::extend('product_unique', function($attribute, $value, $parameters, $validator) {
if ( count(array_unique($value))!=count($value) ) {
return false;
}
return true;
});
}
Finally, in my validation.php I added;
"product_unique" => "Please select a product only once!",
I created database tables users, groups, and group_user (MySQL).And group_user table (intermediate table) contains the user_id and role_id. users and groups relationship is many to many. I want to delete a group in groups table. Before deleting a group, I want to check if there is any user belongs to that group.
I tried to do it this way.
Group.php (Model)
public function users()
{
return $this->belongsToMany('\Modules\User\Models\User');
}
Service.php
public function deleteGroup($data) {
if (!isset($data['groupID']))
return ['error' => 'Failed to delete group. Group id is required'];
$group = Group::find($data['groupID']);
if (!$group)
return ['error' => 'Failed to delete group. Group not found'];
// check any user belongs to group.
$result = $group->users()->pivot->user_id;
if(!$result){
$group->delete();
return ['success' => 'Successfully delete group.'];
}
return ['error' => 'Failed to delete group. Group not found'];
}
But this doesn't work.
I find it out.
service.php
public function deleteGroup($data) {
$group = Group::find($data['groupID']);
if (!$group){
return [
"msg" => "Failed to delete group. Group not found."
];
}
// find out any one belongs to the group.
$result = $group->users->first()->userID;
if ($result){
return [
"msg" => "Failed to delete group. Group has users."
];
}
$result = $group->delete($data['groupID']);
if(!$result){
return [
"msg" => "Failed to delete group."
];
}
return [
"msg" => "Successfully deleted group."
];
}
This is how I do it. If there is another way please tell me. Thanks.