In questa lezione cominceremo ad analizzare la procedura per realizzare la pagina personale di un utente all'interno del nostro e-commerce. Oltre ai dati personali dell'utente e ai suoi ordini vogliamo anche mostrare la sua wish list. Modifichiamo quindi il modello dell'utente in questo modo.
public function wish_list()
{
return $this->hasMany('App\WishList');
}
Il modello della wish list avrà questa struttura.
namespace App;
use Illuminate\Database\Eloquent\Model;
class WishList extends Model
{
protected $table = 'wish_lists';
protected $primaryKey = 'id';
public $incrementing = true;
protected $fillable = ['customer_id', 'product_id'];
}
Ciascun utente viene associato tramite il suo ID e quindi viene associato il prodotto correlato tramite l'ID del prodotto.
Il metodo della route
A questo punto possiamo creare il metodo che gestirà la route del profilo utente all'interno del nostro controller principale.
public function profile()
{
$customer = Customer::find(session()->get('customer_id'));
$wish_list = $customer->wish_list;
$wish_list_product_ids = [];
$countries = Country::all();
$provinces = Province::all();
$cities = Municipality::all();
foreach($wish_list as $item) {
$wish_list_product_ids[] = $item->product_id;
}
$wish_list_products = Product::whereIn('id', $wish_list_product_ids)->get();
return view('profile', [
'title' => 'Profile | PHP E-commerce',
'customer' => $customer,
'wish_list_products' => $wish_list_products,
'countries' => $countries,
'provinces' => $provinces,
'cities' => $cities
]);
}
L'utente corrente viene individuato usando il suo ID salvato nella sessione, quindi vengono reperiti i prodotti della sua wish list usando il metodo whereIn()
che seleziona i record in base agli ID dei prodotti passati nell'array al metodo.
Le variabili $countries
, $provinces
e $cities
rappresentano rispettivamente i record relativi alle nazioni, alle province e alle città che l'utente può selezionare aggiornando i suoi dati di spedizione e di fatturazione.
La password di accesso al sito
La prima cosa che vogliamo che l'utente possa aggiornare nel suo profilo è la sua password di accesso al sito. In Blade avremo il seguente form nella view della route.
<form id="profile-form" action="" method="post" class="pt-lg-5" novalidate>
<div class="form-group">
<label for="password">Password</label>
<input type="text" name="password" id="password" class="form-control password-strength">
</div>
<p>
<input type="hidden" name="customer_id" id="customer_id" value="{{ $customer->id }}">
<input type="submit" value="Save" class="btn btn-primary">
</p>
</form>
Definiamo quindi nel nostro controller AJAX il metodo corrispondente che gestisce l'aggiornamento della password da parte dell'utente.
public function updateCustomer(Request $request)
{
$messages = [
'required' => 'Required field.',
];
if($request->has('password')) {
$rules['password'] = 'required';
}
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return response()->json($validator->messages());
}
$customer = Customer::find($request->get('customer_id'));
if($request->has('password')) {
$customer->password = Hash::make($request->get('password'));
}
$customer->save();
return response()->json(['success' => 'Profile updated successfully.']);
}
Dato che la password se non viene modificata non verrà inviata dal codice lato client, effettuiamo una verifica sulla presenza del corrispondente parametro POST
. Se è presente, aggiungiamo dinamicamente una regola di validazione e provvediamo all'aggiornamento del profilo utente salvando nel database la versione crittata della password.
Il codice del form
Ora possiamo creare il form che permetterà all'utente di modificare i suoi dati di fatturazione e spedizione.
<form id="profile-billing-form" action="" method="post" class="pt-lg-5" novalidate>
<div class="row">
<div class="col-md-6" id="billing-fields">
<h2>Billing</h2>
<div class="form-group">
<label for="billing_address">Address</label>
<input type="text" name="billing_address" id="billing_address" class="form-control" value="{{ $customer->customer_infos->billing_address }}">
</div>
<div class="form-group">
<label for="billing_city">City</label>
<select name="billing_city" id="billing_city" class="form-control">
<option value="">Select...</option>
@foreach($cities as $city)
<option value="{{ $city->name }}" @if($customer->customer_infos->billing_city === $city->name)selected @endif>{{ $city->name }}</option>
@endforeach
</select>
</div>
<div class="form-group">
<label for="billing_country">Country</label>
<select name="billing_country" id="billing_country" class="form-control">
<option value="">Select...</option>
@foreach($countries as $country)
<option value="{{ $country->name }}" @if($customer->customer_infos->billing_country === $country->name)selected @endif>{{ $country->name }}</option>
@endforeach
</select>
</div>
<div class="form-group">
<label for="billing_zip">ZIP</label>
<input type="text" name="billing_zip" id="billing_zip" class="form-control" value="{{ $customer->customer_infos->billing_zip }}">
</div>
<div class="form-group">
<label for="billing_province">Province</label>
<select name="billing_province" id="billing_province" class="form-control">
<option value="">Select...</option>
@foreach($provinces as $province)
<option value="{{ $province->code }}" @if($customer->customer_infos->billing_province === $province->code)selected @endif>{{ $province->name }}</option>
@endforeach
</select>
</div>
</div>
<div class="col-md-6" id="shipping-fields">
<div class="d-flex justify-content-between">
<h2>Shipping</h2>
</div>
<div class="form-group">
<label for="shipping_address">Address</label>
<input type="text" name="shipping_address" id="shipping_address" class="form-control" value="{{ $customer->customer_infos->shipping_address }}">
</div>
<div class="form-group">
<label for="shipping_city">City</label>
<select name="shipping_city" id="shipping_city" class="form-control">
<option value="">Select...</option>
@foreach($cities as $city)
<option value="{{ $city->name }}" @if($customer->customer_infos->shipping_city === $city->name)selected @endif>{{ $city->name }}</option>
@endforeach
</select>
</div>
<div class="form-group">
<label for="shipping_country">Country</label>
<select name="shipping_country" id="shipping_country" class="form-control">
<option value="">Select...</option>
@foreach($countries as $country)
<option value="{{ $country->name }}" @if($customer->customer_infos->shipping_country === $country->name)selected @endif>{{ $country->name }}</option>
@endforeach
</select>
</div>
<div class="form-group">
<label for="shipping_zip">ZIP</label>
<input type="text" name="shipping_zip" id="shipping_zip" class="form-control" value="{{ $customer->customer_infos->shipping_zip }}">
</div>
<div class="form-group">
<label for="shipping_province">Province</label>
<select name="shipping_province" id="shipping_province" class="form-control">
<option value="">Select...</option>
@foreach($provinces as $province)
<option value="{{ $province->code }}" @if($customer->customer_infos->shipping_province === $province->code)selected @endif>{{ $province->name }}</option>
@endforeach
</select>
</div>
</div>
</div>
<div class="row mb-5">
<div class="col-md-6">
<div class="form-group">
<label for="tax_code">Tax code</label>
<input type="text" name="tax_code" id="tax_code" class="form-control" value="{{ $customer->customer_infos->tax_code }}">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="vat_number">VAT number</label>
<input type="text" name="vat_number" id="vat_number" class="form-control" value="{{ $customer->customer_infos->vat_number }}">
</div>
</div>
</div>
<p>
<input type="hidden" name="customer_id" id="customer_id_billing_shipping" value="{{ $customer->id }}">
<input type="submit" value="Save" class="btn btn-primary">
</p>
</form>
Dobbiamo quindi creare il metodo che gestirà via AJAX l'aggiornamento di questi dati.
public function updateBillingShippingFields(Request $request)
{
$messages = [
'required' => 'Required field.',
'digits' => 'Invalid value.',
'alpha_num' => 'Invalid value.'
];
$rules = [
'billing_address' => 'required',
'billing_city' => 'required',
'billing_country' => 'required',
'billing_zip' => 'digits:5',
'billing_province' => 'required',
'shipping_address' => 'required',
'shipping_city' => 'required',
'shipping_country' => 'required',
'shipping_zip' => 'digits:5',
'shipping_province' => 'required',
'tax_code' => 'alpha_num|size:16'
];
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return response()->json($validator->messages());
}
$customer_id = $request->get('customer_id');
$fields = [
'billing_address' => $request->get('billing_address'),
'billing_city' => $request->get('billing_city'),
'billing_country' => $request->get('billing_country'),
'billing_zip' => $request->get('billing_zip'),
'billing_province' => $request->get('billing_province'),
'shipping_address' => $request->get('shipping_address'),
'shipping_city' => $request->get('shipping_city'),
'shipping_country' => $request->get('shipping_country'),
'shipping_zip' => $request->get('shipping_zip'),
'shipping_province' => $request->get('shipping_province'),
'tax_code' => strtoupper($request->get('tax_code')),
'vat_number' => $request->get('vat_number')
];
$info = CustomerInfo::where('customer_id', $customer_id)->get();
$info->update($fields);
return response()->json(['success' => 'Information saved successfully.']);
}
Come si può notare dal codice precedente, l'unico campo facoltativo è il numero di partita IVA, un dato che in futuro potrà servirci per effettuare una distinzione tra le varie tipologie di utenti.