How to store the request data into 3 different tables? - php

I have a form that allows an authenticated user create a new conference.
This form will request the user information and some of this information introduced by the user should be stored in the Conference table, some in the "Conference_Category" table and some in the "RegistrationType" table.
So when the user submit the form "dd($request->all());" shows:
array:20 [▼
"_token" => "DbDKu3ryk4NdxKLr3aO132iHrE0O5b0XqfENk1"
"conference_name" => "Conference Name"
"conference_categories" => "1"
"conference_description" => "description"
"conference_creator_name" => "John"
"conference_creator_email" => "email#testemail.email"
"conference_creator_description" => "description"
"registration_type_name" => "registration type name"
"registration_type_description" => "registration type desc"
"registration_type_capacity" => "100"
]
DOUBT
My doubt is how to properly store this request information. Because its necessary to store the request data into 3 different tables to create a new conference:
In the "Conference" table is necessary to store: the conference_name, conference_description, conference_creator_id, conference_creator_name,conference_creator_email, conference_creator_description
In the "conference_category" table is necessary to store: the conference categories id's and the conference id
In the "RegistrationType" table is necessary to store:registration_type_name, registration_type_description and registration_type_capacity
I have a ConferenceController and I have the logic to create a new conference in the store() method of the ConferenceController. But for now I just have the part to store the request information on the Conference table.
Do you know how to also store the categories introduced by the user and the registration type in the respective tables (conference_category and RegistrationType)?
ConferenceController create method:
<?php
namespace App\Http\Controllers;
use App\Category;
use App\Conference;
use Illuminate\Http\Request;
class ConferenceController extends Controller
{
public function store(Request $request)
{
dd($request->all());
$this->validate($request, [
'conference_name' => 'required|max:255',
'conference_categories' => 'required|array|between:1,3',
'conference_startDate' => 'required',
'conference_creator_name' => 'required',
'conference_creator_email' => 'required|email|unique:users',
'conference_creator_description' => '',
'conference_registration_type_name' => 'required',
'confenrece_registration_type_description' => '',
'conference_registration_type_capacity' => 'required',
]);
$conference = Conference::create([
'name' => $request->conference_name,
'description' => $request->conference_description,
'startDate' => $request->conference_startDate,
'conference_creator_id' => Auth::user()->id,
'conference_creator_name' => $request->conference_creator_name,
'conference_creator_email' => $request->conference_creator_email,
'conference_creator_description' => $request->conference_creator_description
]);
}
}
The relationships relevants for this questions are:
Many to many between Conference and Categories (A conference can have many categories, so there is a third table conference_category)
one to many between User and Conference (A user can create many conferences)
one to many between Conference and RegistrationType (A conference can have many registration types)
Conference Model
class Conference extends Model
{
protected $fillable = [
'name', 'description', 'startDate', '...'
];
public function categories(){
return $this->belongsToMany('App\Category');
}
public function conference_creator(){
return $this->belongsTo('App\User', 'conference_creator_id');
}
public function registrationTypes(){
return $this->hasMany('App\RegistrationType', 'conference_id');
}
}
Category Model:
class Category extends Model
{
public function conferences(){
return $this->belongsToMany('App\Conference');
}
}
RegistrationType Model:
class RegistrationType extends Model
{
public function conference(){
return $this->belongsTo('App\Conference');
}
}
User Model:
class User extends Authenticatable
{
use Notifiable;
protected $fillable = [
'name', 'email', 'password'
];
protected $hidden = [
'password', 'remember_token',
];
public function conferences(){
return $this->hasMany('App\Conference');
}
}

For the Category you want a Many-to-Many relation. Because a Conference can have many Categories and a Category can have many Conferences. You have already set this up correctly in your Models.
After you have created your Conference you can add the categories to the Conference, this can be done using the Attach method(Assuming that the given ids do exist, if not you'll have to check that first):
$conference->categories()->attach($request->conference_categories);
For more information about Attach: Laravel Eloquent
For the RegistrationType, I assume from your Models that a Conference can have multiple RegistrationTypes and a RegistrationType can only have 1 Conference.
You will have to add the following $fillables to your RegistrationType Model:
protected $fillable = ['name', 'description', 'capacity', 'conference_id'];
After you have created your Conference you can create the RegistrationType:
RegistrationType::create([
'conference_id' => $conference->id,
'name' => $request->conference_registration_type_name,
'description' => $request->confenrece_registration_type_description,
'capacity' => $request->conference_registration_type_capacity
]);
End result:
$conference = Conference::create([
'name' => $request->conference_name,
'description' => $request->conference_description,
'startDate' => $request->conference_startDate,
'conference_creator_id' => Auth::user()->id,
'conference_creator_name' => $request->conference_creator_name,
'conference_creator_email' => $request->conference_creator_email,
'conference_creator_description' => $request->conference_creator_description
]);
$conference->categories()->attach($request->conference_categories);
RegistrationType::create([
'conference_id' => $conference->id,
'name' => $request->conference_registration_type_name,
'description' => $request->confenrece_registration_type_description,
'capacity' => $request->conference_registration_type_capacity
]);

Related

CakePHP 3: saving hasOne association ($_accessible not set)

I have read several Stack Overflow posts and the documentation pages about saving associated data in CakePHP 3, but I can't get my code to work. When creating a new Organisation, I also want to save the data of the new account (NewAccount) that belongs to that Organisation.
Below is a reproducible part of my code. The validation of the Organisations model are executed and if passed, the data is saved. The NewAccounts data does not get saved, and is not even being validated. I have already checked the naming conventions in all of these files, but I can't find anything that might be a problem anymore.
// Model/Table/OrganisationsTable.php
class OrganisationsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->hasOne('NewAccounts');
}
}
// Model/Table/NewAccountsTable.php
class NewAccountsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->belongsTo('Organisations', [
'foreignKey' => 'organisation_id'
]);
}
}
// Template/Organisations/admin_add.ctp
echo $this->Form->create($organisation);
echo $this->Form->control('new_account.email', [
'label' => __('Email address'),
'class' => 'form-control',
]);
echo $this->Form->control('new_account.name', [
'label' => __('Name'),
'class' => 'form-control',
]);
echo $this->Form->control('name', [
'label' => __('Organisation name'),
'div' => 'form-group',
'class' => 'form-control',
]);
// Controller/OrganisationsController.php
class OrganisationsController extends AppController
{
public function adminAdd() {
$organisation = $this->Organisations->newEntity();
if($this->request->is('post')) {
$this->Organisations->patchEntity($organisation, $this->request->getData(), [
'associated' => ['NewAccounts']
]);
if ($this->Organisations->save($organisation)) {
$id = $organisation->id;
debug("Success!");
}
else {
debug("Error");
}
}
$this->set(compact('organisation'));
}
}
CakePHP documentation I have referenced:
Saving Data
Form
Associations - Linking Tables Together
Validating Data
Entities
I forgot to make $organisation->new_account accessible:
// Model/Entity/Organisation.php
class Organisation extends Entity
{
protected $_accessible = [
// ...
'new_account' => true,
];
}
By doing this, the field is marked as to be safely assigned.
Entities: Mass Assignment (book) and EntityTrait::$_accessible (API docs)

how to use laravel eloquent to get and display data from other tables

I was using these codes in my controller to get all the data from my 2 tables and it works fine
$All = Customers::with('order')->paginate(10);
return response()->json([
'code' => 0,
'success' => true,
'data' => $All
], 200);
Here is how I define the relationship between these 2 tables
class Customers extends Model
{
public function order()
{
return $this->hasMany(Orders::class, 'customer_id', 'id');
}
}
class Orders extends Model
{
public function customers()
{
return $this->belongsTo(Customers::class, 'customer_id', 'id');
}
}
Now my desire output is to hide the order id, order timestamps and change the customer_id to customer's name (the customer's name is not in my orders db table).
I'm using 'data' => DataResource::collection($All) in my controller and this is my DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => $this->order
];
}
and of course the output is same with the image above.
My database structure:
orders table:
customer table:
Can anyone help me with that?
The answer is simple and basically a copy of the official documentation. You simply need to wrap your orders in an OrderResource as well.
// DataResource
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'order' => OrderResource::collection($this->order)
];
}
// OrderResource
public function toArray($request)
{
return [
'items' => $this->items,
'quantity' => $this->quantity
];
}
I don't really understand why you would want to include the customer_name in your orders when it is already present on the customers object one hierarchy above. But if you really want to add it, you should be able to do so with: 'customer_name' => $this->customers->name.
As a side note: you really should be more consistent with your naming. Why is the resource called DataResource when it is about Customers? Why is your model called Customers in plural form rather than Customer in singular, which is the convention (and more logical if you consider that one model represents one customer). Why is your belongsTo relation called customers() in plural when it returns one customer, while your hasMany relation is called order whereas it returns one or more orders?

Polymorphic relationships

I've got a master table called Product with the following columns:
id
product_id
product_type
name
price
in_stock
upc
Where ’id' and 'product_id' are unique (id is the PK)
I'll have other tables for different kinds of products (types).
All these other tables will have Product’s properties plus
Other properties on their own depending on the type of product
(I.e. clothing, records, etc.).
So I created a Product model using Polymorphic relationships
as follows:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'product_id',
'product_type',
'name',
'price',
'in_stock',
'upc'
];
public function categorizable()
{
return $this->morphTo();
}
}
And, for instance, a records model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Record extends Model
{
protected $fillable = [
    'artist_id',
    'title',
    'label',
    'code',
    'format',
    'number_of_discs',
    'image',
    'description'
];
public function products()
{
return $this->morphMany('\App\Product', 'categorizable');
}
public function artist()
{
return $this->belongsTo(Artist::class);
}
public function track()
{
return $this->hasMany(Track::class);
}
public function getItemDetails(int $itemId): array {
}
}
Whereas the columns for record are:
id
artist_id
product_id
title
label
This is the best way I could think of relating these tables.
My questions are:
Is there a better approach to this specific problem?
In this case (using polymorphic relationships), how would I insert a product?
How could I query a product in order to return data from
Both product table and record table? I mean, not a raw query
Since that I can do, but how to perform this query using
Eloquent?
Your code is perfect except product_id column in Record. You don't need that column, just remove it
how would I insert a product?
$product = Product::create([
'name' => $request->name,
'price' => $request->price,
'in_stock' => $request->in_stock
]);
$record->products()->save($product);
OR
$record->products()->create([
'name' => $request->name,
'price' => $request->price,
'in_stock' => $request-> in_stock,
'product_id' => $record->id,
'product_type' => get_class($record)
]);
If you need to create both then do it like this
$record = Record::create([
'artist_id' => $request->artist_id
'title' => $request->title,
'label' => $request->label,
'code' => $request->code,
]);
$product = Product::create([
'name' => $request->name,
'price' => $request->price,
'in_stock' => $request->in_stock
]);
$record->products()->save($product);
Fetch Data
$product = Product::with('categorizable')->find(2);
$product->categorizable; //this will be either Record, Cloth... instance
Similarly for record
$record = Record::with('products')->find(1);
$record->products; //it will give you product collection
For details you can look https://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations

Laravel updateOrCreate on OneToOne relationShip

in my web application i have this models:
InstagramAccount.php
UserPageFeed.php
each InstagramAccount has one record into UserPageFeed and each UserPageFeed belongs to one record into InstagramAccount, then that's one to one relationship,
PROBLEM:
my below code couldn't update existing row on table and create again
$userSelectedPage = InstagramAccount::whereUsername('my_page')->first();
$userPageFeeds = new UserPageFeed();
$userSelectedPage->account()->updateOrCreate([
'instagram_account_id' => $userPageFeeds->id, //exsiting row
'page_name' => 'test',
'feeds' => 'test',
'cache_time' => Carbon::now()->addHour(6),
]);
or this code:
$userSelectedPage = InstagramAccount::whereUsername('content.world')->first();
$salam = $userSelectedPage->account()->updateOrCreate([
'instagram_account_id' => $userSelectedPage->id,
'page_name' => 'aaaaaaa',
'feeds' => 'ddd',
'cache_time' => Carbon::now()->addHour(6),
]);
user_page_feeds table structure:
id ->Primary
instagram_account_id ->Index
feeds
page_name
cache_time
created_at
updated_at
with this index:
"Keyname":user_page_feeds_instagram_account_id_foreign "Column":instagram_account_id
instagram_accounts table structure:
id ->Primary
user_id ->Index
uid
fid
proxy
avatar
username
password
checkpoint
account_data
people_data
status
created_at
updated_at
InstagramAccount model:
class InstagramAccount extends Model
{
protected $guarded = ['id'];
protected $casts = [
'account_data' => 'array',
'people_data' => 'array'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function account()
{
return $this->hasOne(UserPageFeed::class);
}
}
UserPageFeed model:
class UserPageFeed extends Model
{
public $incrementing = false;
protected $guarded = ['id'];
protected $casts = [
'feeds' => 'array'
];
public function account()
{
return $this->belongsTo(InstagramAccount::class,'instagram_account_id');
}
}
You have to use updateOrCreate() with two separate parameters:
$userSelectedPage->account()->updateOrCreate(
['instagram_account_id' => $userPageFeeds->id],
[
'page_name' => 'test',
'feeds' => 'test',
'cache_time' => Carbon::now()->addHour(6),
]
);
The first parameter contains the attributes that Laravel uses to find the existing
account.
The second parameter contains the attributes that Laravel uses to create or update the account.

Inserting values to a form with relationship in laravel (Referring projectid)

There is a a single form which takes in details and save it to 4 different tables in db. Project, Events, Donation and Opportunities. Project has many Events, many Donation and many Opportunities. I want to use the project id in other tables as well. but when I save the Form the details are stored in each 4 tables but the project is not been taken for the other 3 tables Events, Donation and Opportunity. Its value is 0. How to take that particular project id(auto-increment) in all other three tables.
My ProjectController is like this:
class ProjectController extends Controller
{
public function getProject()
{
return view ('other.project');
}
public function postProject(Request $request)
{
$this->validate($request, [
'ptitle' => 'required|max:200',
'pdescription' => 'required',
'etitle' => 'required|max:200',
'edetails' => 'required',
'dtotal' => 'required',
'oposition' => 'required|max:100',
'odescription' => 'required',
]);
Project::create([
'ptitle' => $request->input('ptitle'),
'pdescription' => $request->input('pdescription'),
'pduration' => $request->input('pduration'),
'psdate' => $request->input('psdate'),
'pedate' => $request->input('pedate'),
'pcategory' => $request->input('pcategory'),
'pimage' => $request->input('pimage'),
]);
Event::create([
'pro_id' => $request->input('pid'),
'etitle' => $request->input('etitle'),
'pdetails' => $request->input('pdetails'),
'edate' => $request->input('edate'),
'etime' => $request->input('etime'),
'elocation' => $request->input('elocation'),
'eimage' => $request->input('eimage'),
]);
Donation::create([
'pro_id' => $request->input('pid'),
'dtotal' => $request->input('dtotal'),
'dinhand' => $request->input('dinhand'),
'dbankaccount' => $request->input('dbankaccount'),
]);
Opportunity::create([
'pro_id' => $request->input('pid'),
'oposition' => $request->input('oposition'),
'odescription' => $request->input('odescription'),
'olocation' => $request->input('olocation'),
'odeadline' => $request->input('odeadline'),
]);
return redirect()
->route('home')
->with('info', 'Your project has been created.');
}
My Project Model:
class Project extends Model
{
use Notifiable;
protected $fillable = [
'ptitle',
'pdescription',
'pduration',
'psdate',
'pedate',
'pcategory',
'pimage',
];
public function events()
{
return $this->hasMany('Ngovol\Models\Event', 'pro_id');
}
public function donations()
{
return $this->hasMany('Ngovol\Models\Donation', 'pro_id');
}
public function opportunities()
{
return $this->hasMany('Ngovol\Models\Event', 'pro_id');
}
protected $hidden = [
];
}
Event Model:
class Event extends Model
{
use Notifiable;
protected $table = 'events';
protected $fillable = [
'pro_id',
'etitle',
'edetails',
'edate',
'etime',
'elocation',
'eimage',
];
public function projects()
{
return $this->belongsTo('Ngovol\Models\Project', 'pro_id');
}
}
Donation Model:
class Donation extends Model
{
use Notifiable;
protected $fillable = [
'pro_id',
'dtotal',
'dinhand',
'drequired',
'dbankaccount',
];
protected $hidden = [
];
public function projects()
{
return $this->belongsTo('Ngovol\Models\Project', 'pro_id');
}
}
Opportunity Model:
class Opportunity extends Model
{
use Notifiable;
protected $fillable = [
'pro_id',
'oposition',
'odescription',
'olocation',
'odeadline',
];
protected $hidden = [
];
public function projects()
{
return $this->belongsTo('Ngovol\Models\Project', 'pro_id');
}
}
Better try following code
$project = Project::create( $request->only(['ptitle', 'pdescription', 'pduration', 'psdate', 'pedate', 'pcategory', 'pimage']));
$project->events()->create( $request->only(['etitle', 'pdetails', 'edate', 'etime', 'elocation', 'eimage']));
$project->donations()->create($request->only(['dtotal', 'dinhand', 'dbankaccount']));
$project->opportunities()->create($request->only(['oposition','odescription','olocation','odeadline']));

Categories