I create a service to encrypt and decrypt my data in my database.
So when I create a new Fiche or update one, I encrypt the name and the surname
Here my subscriber FicheEntitySubscriber :
class FicheEntitySubscriber implements EventSubscriberInterface
{
private $security;
private $encryptionService;
public function __construct(Security $security, EncryptionService $encryptionService)
{
$this->security = $security;
$this->encryptionService = $encryptionService;
}
public static function getSubscribedEvents(): array
{
return [
BeforeEntityPersistedEvent::class => ['setFicheEntity', 10],
BeforeEntityUpdatedEvent::class => ['setFicheEntity', 10]
];
}
/**
* #throws Exception
*/
public function setFicheEntity(AbstractLifecycleEvent $event)
{
$entity = $event->getEntityInstance();
if (!($entity instanceof FicheEntity)) {
return;
}
if ($event instanceof BeforeEntityPersistedEvent) {
$entity->setUtilisateur($this->security->getUser());
}
$entity->setNom($this->encryptionService->encrypt_decrypt('encrypt', mb_strtoupper($entity->getNom())));
$entity->setPrenom($this->encryptionService->encrypt_decrypt('encrypt', mb_strtoupper($entity->getPrenom())));
}
}
Here my FicheController :
class FicheEntityCrudController extends AbstractCrudController
{
private $_adminContextFactory;
private $encryptService;
private $ficheEntityRepo;
public function __construct(AdminContextFactory $adminContextFactory, EncryptionService $encryptionService, FicheEntityRepository $ficheEntityRepo)
{
$this->_adminContextFactory = $adminContextFactory;
$this->encryptService = $encryptionService;
$this->ficheEntityRepo = $ficheEntityRepo;
}
public static function getEntityFqcn(): string
{
return FicheEntity::class;
}
public function configureCrud(Crud $crud): Crud
{
return $crud
->setEntityLabelInPlural('Fiches')
->setEntityLabelInSingular('Fiche informative')
->setSearchFields(['nom', 'prenom', 'nomAntibio'])
->setPaginatorPageSize(10)
->setPaginatorRangeSize(2);
}
public function configureFilters(Filters $filters): Filters
{
return $filters
->add(TextFilter::new('nomAntibio')->setLabel('Nom ATB'))
->add(DateTimeFilter::new('dateDebut')->setLabel('Date Debut'))
->add(DateTimeFilter::new('dateRappel3Jour')->setLabel('Rappel 3e Jour'))
->add(DateTimeFilter::new('dateRappel7Jour')->setLabel('Rappel 7e Jours'));
}
public function configureActions(Actions $actions): Actions
{
$export = Action::new('exportAction', 'Export')
->setIcon('fa fa-download')
->linkToCrudAction('exportAction')
->setCssClass('btn')
->createAsGlobalAction();
return $actions
->add(Crud::PAGE_INDEX, $export);
}
public function exportAction(Request $request): Response
{
$context = $this->_getEasyAdminRefererContext($request);
$searchDto = $this->_adminContextFactory->getSearchDto($request, $context->getCrud());
$fields = FieldCollection::new($this->configureFields(Crud::PAGE_INDEX));
$filters = $this->get(FilterFactory::class)->create($context->getCrud()->getFiltersConfig(), $fields, $context->getEntity());
$result = $this->createIndexQueryBuilder(
$searchDto, $context->getEntity(), $fields, $filters
)
->getQuery()->getResult();
$data = [];
/**
* #var $record FicheEntity
*/
foreach ($result as $record) {
$data[] = [
'Nom Complet' => $record->getFullname(),
'Chambre' => $record->getChambre(),
'Date Debut' => $record->getDateDebut()->format('y-m-d'),
'Duree ATB' => $record->getDureeJour(),
'Nom ATB' => $record->getNomAntibio(),
'Rappel 3e Jour' => ($record->getDateRappel3Jour() !== null ? $record->getDateRappel3Jour()->format('y-m-d') : $record->getDateRappel3Jour()),
'Réévalué' => ($record->getDateRappel3Jour() !== null ? ($record->getReevalue() === true ? 'oui' : 'non') : ''),
'Rappel 7e Jour' => ($record->getDateRappel7Jour() !== null ? $record->getDateRappel7Jour()->format('y-m-d') : $record->getDateRappel7Jour()),
'Justifié' => ($record->getDateRappel7Jour() !== null ? ($record->getJustifie() === true ? 'oui' : 'non') : ''),
'Pathologie' => $record->getPathologie(),
'Hospitalier' => ($record->getHospitalier() === true ? 'oui' : '')
];
}
$filename = 'export_fiche_' . date_create()->format('d-m-y H:i:s') . '.csv';
$serializer = new Serializer([new ObjectNormalizer()], [new CsvEncoder()]);
$response = new Response($serializer->encode($data, CsvEncoder::FORMAT));
$response->headers->set('Content-Type', 'text/csv; charset=utf-8');
$response->headers->set('Content-Disposition', "attachment; filename=\"$filename\"");
return $response;
}
private function _getEasyAdminRefererContext(Request $request)
{
\parse_str(\parse_url($request->query->get(EA::REFERRER))[EA::QUERY], $referrerQuery);
if (array_key_exists(EA::FILTERS, $referrerQuery)) {
$request->query->set(EA::FILTERS, $referrerQuery);
}
return $request->attributes->get(EA::CONTEXT_REQUEST_ATTRIBUTE);
}
public function configureFields(string $pageName): iterable
{
return [
IntegerField::new('id')->hideOnForm()->hideOnIndex(),
TextField::new('nom')->hideOnIndex()->setColumns(6),
TextField::new('prenom')->hideOnIndex()->setColumns(6),
TextField::new('fullname')->setLabel('Nom complet')->hideOnForm(),
IntegerField::new('chambre')->setColumns(4),
TextField::new('nomAntibio')->setLabel('Nom ATB')->setColumns(4),
IntegerField::new('dureeJour')->setLabel('Durée ATB TTT')->setColumns(4),
DateField::new('dateDebut'),
DateField::new('dateRappel3Jour')->setLabel('Rappel 3e Jour')->hideOnForm(),
BooleanField::new('reevalue')->setLabel('Réévalué')->hideOnForm(),
DateField::new('dateRappel7Jour')->setLabel('Rappel 7e Jour')->hideOnForm(),
BooleanField::new('justifie')->setLabel('Justifié')->hideOnForm(),
TextField::new('pathologie'),
AssociationField::new('utilisateur', 'Admin')->setLabel('Utilisateur')->hideOnForm(),
BooleanField::new('hospitalier')
];
}
My issue is that when I display my list of fiches, I want to decrypt the encrypted data, for now I try :
use the AfterEntityBuiltEvent (did not working)
listen on Event postLoad
create an custom action
but none of these are working. Does someone try something similar ?
Thanks in advance
This question already has answers here:
Laravel 5.4 field doesn't have a default value
(10 answers)
Closed 1 year ago.
Good afternoon to y'all!
Somewhere in the past week, I changed something in the website that caused the following error:
SQLSTATE[HY000]: General error: 1364 Field 'identifier' doesn't have a default value (SQL: insert into `classifieds` (`vehicle_id`, `vehicle_type`, `updated_at`, `created_at`) values (19983, App\Models\Car, 2021-04-27 16:27:56, 2021-04-27 16:27:56))
It's is very weird, because the $fillable is set (and it worked before).
This is the content being used:
Classified Model:
<?php
namespace App\Models;
use App\Http\Controllers\Controller;
use App\Rules\FileUploader;
use App\Rules\VehicleRegDate;
use Auth;
use Cache;
use CyrildeWit\EloquentViewable\Contracts\Viewable;
use CyrildeWit\EloquentViewable\InteractsWithViews;
use Eloquent;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Rennokki\QueryCache\Traits\QueryCacheable;
use ShiftOneLabs\LaravelCascadeDeletes\CascadesDeletes;
use Throwable;
/**
* App\Models\Classified
*
* #property int $id
* #property string $identifier
* #property int|null $vehicle_id
* #property string|null $vehicle_type
* #property int $proprietor_id
* #property string $proprietor_type
* #property float $price
* #property Carbon|null $created_at
* #property Carbon|null $updated_at
* #property-read Collection|Equipment[] $equipments
* #property-read int|null $equipments_count
* #property-read Collection|Media[] $medias
* #property-read int|null $medias_count
* #property-read Model|Eloquent $proprietor
* #property-read Model|Eloquent $vehicle
* #method static Builder|Classified newModelQuery()
* #method static Builder|Classified newQuery()
* #method static Builder|Classified query()
* #method static Builder|Classified whereCreatedAt($value)
* #method static Builder|Classified whereId($value)
* #method static Builder|Classified whereIdentifier($value)
* #method static Builder|Classified wherePrice($value)
* #method static Builder|Classified whereProprietorId($value)
* #method static Builder|Classified whereProprietorType($value)
* #method static Builder|Classified whereUpdatedAt($value)
* #method static Builder|Classified whereVehicleId($value)
* #method static Builder|Classified whereVehicleType($value)
* #mixin Eloquent
* #property string|null $identifier_old
* #property float $lat
* #property float $lng
* #property string|null $video_embed
* #property int|null $phone
* #property int|null $type
* #property int $status
* #property-read Collection|Advertising[] $adverts
* #property-read int|null $adverts_count
* #property-read Collection|Feature[] $features
* #property-read int|null $features_count
* #property-read Collection|Message[] $messages
* #property-read int|null $messages_count
* #property-read Collection|PriceOption[] $price_options
* #property-read int|null $price_options_count
* #property-read Sharing|null $sharing
* #method static Builder|Classified whereIdentifierOld($value)
* #method static Builder|Classified whereLat($value)
* #method static Builder|Classified whereLng($value)
* #method static Builder|Classified wherePhone($value)
* #method static Builder|Classified whereStatus($value)
* #method static Builder|Classified whereType($value)
* #method static Builder|Classified whereVideoEmbed($value)
*/
class Classified extends Model implements Viewable
{
use CascadesDeletes, QueryCacheable, InteractsWithViews;
const STATUS_INACTIVE = 0;
const STATUS_ACTIVE = 1;
const STATUS_PENDING = 2;
const STATUS_RETOUCH = 3;
const STATUS_ARCHIVED = 4;
const STATUS_REFUSED = 5;
const STATUS_EXPIRED = 6;
protected static $flushCacheOnUpdate = true;
public $cacheFor = 86400;
protected $fillable = [
'identifier',
'identifier_old',
'proprietor_id',
'proprietor_type',
'price',
'lat',
'lng',
'video_embed',
'phone',
'type',
'status',
'created_at',
'updated_at'
];
protected $hidden = [
'id',
'identifier_old',
'proprietor_id',
'proprietor_type',
'vehicle_id',
'vehicle_type',
'lat',
'lng',
'phone',
];
protected array $cascadeDeletes = ['medias', 'equipments', 'features', 'price_options', 'messages', 'adverts', 'sharing'];
public array $rules = [
'classified',
'car',
'motorcycle',
'bike'
];
public function __construct()
{
$this->rules['classified'] = [
'vehicle_type' => 'required|alpha|in:car,motorcycle,bike',
'type' => 'required|integer|exists:vehicle_data,id',
'price' => 'required|numeric|min:1',
'price_options.*' => 'nullable|integer|min:1',
'features.*' => 'nullable|integer|exists:vehicle_data,id',
'equipments.*' => 'nullable|integer|exists:vehicle_data,id',
'fileuploader-list-files' => ['required', 'json', new FileUploader],
'phone' => 'nullable|numeric|digits:9',
'address' => 'nullable|string',
'terms' => 'required|boolean',
];
$this->rules['car'] = [
'make' => 'required|integer|exists:vehicle_data,id',
'model' => 'required|integer|exists:vehicle_data,id',
'version' => 'nullable|string',
'fuel' => 'required|integer|exists:vehicle_data,id',
'firstRegDate' => ['required', new VehicleRegDate()],
'mileage' => 'required|integer|min:0',
'displacement' => 'required|integer|min:1',
'power_kw' => 'nullable|integer|min:1',
'power_hp' => 'nullable|integer|min:1',
'bodyType' => 'required|integer|exists:vehicle_data,id',
'bodyColour' => 'required|integer|exists:vehicle_data,id',
'vin' => 'nullable|string|min:17|max:17',
'annotations' => 'nullable|string',
'transmission' => 'nullable|integer|exists:vehicle_data,id',
'gears' => 'nullable|integer|exists:vehicle_data,id',
'doors' => 'nullable|integer|exists:vehicle_data,id',
'seats' => 'nullable|integer|exists:vehicle_data,id',
'vehicle_class' => 'nullable|integer|exists:vehicle_data,id',
'driveTrainType' => 'nullable|integer|exists:vehicle_data,id',
'maxFuelRange' => 'nullable|numeric|min:1',
'emission' => 'nullable|numeric|min:0.01',
'iuc' => 'nullable|numeric|min:1',
'particleFilter' => 'nullable|boolean',
'warrantyDate' => 'nullable|date_format:d-m-Y',
'warrantyKM' => 'nullable|integer|min:1',
'inspectionDate' => 'nullable|date_format:d-m-Y',
'registries' => 'nullable|integer|exists:vehicle_data,id',
'origin' => 'nullable|integer|exists:vehicle_data,id',
'license' => 'nullable|string',
'fuelConsumptionCity' => 'nullable|numeric|min:1',
'fuelConsumptionHighway' => 'nullable|numeric|min:1',
'fuelConsumptionAverage' => 'nullable|numeric|min:1',
'vintage' => 'nullable|boolean',
'video_embed' => 'nullable|string'
];
$this->rules['bike'] = [
'framework' => 'nullable|string',
'wheel-size' => 'nullable|numeric|min:1',
'material' => 'nullable|string',
'suspension' => 'nullable|string',
'suspension-travel' => 'nullable|string',
'shock-absorber' => 'nullable|string',
'damping-travel' => 'nullable|string',
'type-of-brake' => 'nullable|string',
'brakes' => 'nullable|string',
'speeds' => 'nullable|string',
'gearshift-lever' => 'nullable|string',
'rear-change' => 'nullable|string',
'casset' => 'nullable|string',
'chain' => 'nullable|string',
'pedal' => 'nullable|string',
'roses' => 'nullable|string',
'cubes' => 'nullable|string',
'tires' => 'nullable|string',
'steering-gearbox' => 'nullable|string',
'advance' => 'nullable|string',
'guideline' => 'nullable|string',
'fingers' => 'nullable|string',
'saddle' => 'nullable|string',
'seat-post' => 'nullable|string',
'brand' => 'nullable|string',
'warranty' => 'nullable|string',
'hard-tail-full-suspension' => 'nullable|string',
'year' => 'nullable|integer|min:1990|max:' . date('Y'),
'engine' => 'nullable|string',
'battery' => 'nullable|string',
];
parent::__construct();
}
public function proprietor(): MorphTo
{
return $this->morphTo();
}
public function vehicle(): MorphTo
{
return $this->morphTo();
}
public function equipments(): BelongsToMany
{
return $this->belongsToMany(VehicleData::class, 'classified_equipment', 'classified_id', 'equipment_id');
}
public function features(): BelongsToMany
{
return $this->belongsToMany(VehicleData::class, 'classified_feature', 'classified_id', 'feature_id');
}
public function price_options(): BelongsToMany
{
return $this->belongsToMany(VehicleData::class, 'classified_price_option', 'classified_id', 'price_option_id');
}
public function messages(): HasMany
{
return $this->hasMany(Message::class);
}
public function adverts(): HasMany
{
return $this->hasMany(Advertising::class);
}
public function sharing(): MorphOne
{
return $this->morphOne(Sharing::class, 'object');
}
public function medias(): MorphMany
{
return $this->morphMany(Media::class, 'mediable');
}
public function getFeaturedMedia($size = null): string
{
try {
if ($media = $this->medias()->orderBy('index', 'ASC')->first())
return $media->getMediaRoute($size);
if ($this->video_embed)
return sprintf("https://i.ytimg.com/vi/%s/hqdefault.jpg", $this->video_embed);
throw new Exception();
} catch (Throwable $exception) {
return asset_cdn('assets/img/default_listing.jpg');
}
}
public function getRoute(): string
{
return route("classified.show", [$this->identifier, $this->getSlug()]);
}
public function getSlug(): string
{
return Str::slug($this->getTitle());
}
public function getTitle($size = null)
{
try {
if ($this->isOtherMake() && $this->isOtherModel())
$title = $this->vehicle->version;
elseif ($this->isOtherMake())
$title = $this->getModelName() . " " . $this->vehicle->version;
else
$title = $this->getMakeName() . " " . $this->getModelName() . " " . $this->vehicle->version;
if ($size)
return Str::limit($title, $size);
return $title;
} catch (Throwable $exception) {
return $this->vehicle->version;
}
}
public function getVehicleType(): ?string
{
try {
return strtolower(explode("\\", $this->vehicle_type)[2]);
} catch (Throwable $exception) {
return null;
}
}
public function getMakeName()
{
try {
return (new Controller())->getVehicleMakeByAttr($this->getVehicleType(), $this->vehicle->make, 'id', 'value');
} catch (Throwable $exception) {
return null;
}
}
public function getMakeNameOld()
{
try {
return config('constants.' . $this->getVehicleType() . '.makes.' . $this->vehicle->make);
} catch (Throwable $exception) {
return null;
}
}
public function getModelName()
{
try {
return (new Controller())->getVehicleModelByModelAttr($this->getVehicleType(), $this->vehicle->make, $this->vehicle->model, 'id', 'value');
} catch (Throwable $exception) {
return null;
}
}
public function getModelNameOld()
{
try {
return config('constants.' . $this->getVehicleType() . '.models.' . $this->vehicle->make . '.' . $this->vehicle->model);
} catch (Throwable $exception) {
return null;
}
}
public function getFirstRegDate()
{
try {
return Carbon::parse($this->vehicle->firstRegDate);
} catch (Throwable $exception) {
return Carbon::parse($this->vehicle->firstRegDate);
}
}
public function getFuelType()
{
$fuelType = Cache::get(sprintf("vehicle_data_%s_%s_%s_leaf", "classified", "fuel", $this->vehicle->fuel));
try {
return $fuelType->value;
} catch (Throwable $exception) {
return "Outro";
}
}
public function getVersion($size = null)
{
try {
if ($size)
return Str::limit($this->vehicle->version, $size);
else
return $this->vehicle->version;
} catch (Throwable $exception) {
return null;
}
}
public function getFormattedNumber($number, $decimal = 0)
{
return number_format($number, $decimal, ',', ' ');
}
public function getBodyTypeName()
{
try {
$bodyType = Cache::get(sprintf("vehicle_data_%s_%s_%s", $this->getVehicleType(), "bodyTypes", $this->vehicle->bodyType));
return $bodyType->first()->value;
} catch (Throwable $exception) {
return "Outro";
}
}
public function getBodyColourName() // Fix
{
try {
$object = VehicleData::findOrFail($this->vehicle->bodyColour);
return $object->value;
} catch (Throwable $exception) {
return "Outro";
}
}
public function getTransmissionName()
{
try {
$object = VehicleData::findOrFail($this->vehicle->transmission);
return $object->value;
} catch (Throwable $exception) {
return null;
}
}
public function getGearsNumber()
{
try {
$object = VehicleData::findOrFail($this->vehicle->gears);
return $object->value;
} catch (Throwable $exception) {
return null;
}
}
public function getDoorsNumber()
{
try {
$object = VehicleData::findOrFail($this->vehicle->doors);
return $object->value;
} catch (Throwable $exception) {
return null;
}
}
public function getClassName()
{
try {
$object = VehicleData::findOrFail($this->vehicle->vehicle_class);
return $object->value;
} catch (Throwable $exception) {
return null;
}
}
public function getOriginName()
{
try {
$object = VehicleData::findOrFail($this->vehicle->origin);
return $object->value;
} catch (Throwable $exception) {
return null;
}
}
public function getLicenseFormated()
{
try {
$license = strtoupper($this->vehicle->license);
if (strlen($license) == 6) {
$parts = str_split($license, 2);
return implode('-', $parts);
}
return $license;
} catch (Throwable $exception) {
return "00-00-00";
}
}
public function getDriveTrainTypeName()
{
try {
$object = VehicleData::findOrFail($this->vehicle->driveTrainType);
return $object->value;
} catch (Throwable $exception) {
return null;
}
}
public function getDateFormated($date)
{
return Carbon::parse($date)->format('d-m-Y');
}
public function getDateStatus($date)
{
if (Carbon::parse($this->vehicle->$date) >= Carbon::today()->addDays(30))
return "warning";
elseif (Carbon::parse($this->vehicle->$date) < Carbon::today())
return "danger";
else
return "info";
}
public function getVehicleTypeClassByName($name, $class = null)
{
switch ($name) {
case "car":
if (!$class)
return "App\Models\Car";
else
return Car::class;
case "motorcycle":
if (!$class)
return "App\Models\Motorcycle";
else
return Motorcycle::class;
default:
return null;
}
}
public function getVehicleTypeByClass()
{
switch ($this->vehicle_type) {
case Car::class:
return 'car';
case Motorcycle::class:
return 'motorcycle';
default:
return null;
}
}
public function getVehicleTypeNameByClass()
{
switch ($this->vehicle_type) {
case Car::class:
return 'Carro';
case Motorcycle::class:
return 'Moto';
default:
return null;
}
}
public function getPhoneViews()
{
return 0;
}
public function getStatusElements()
{
return config('constants.status.' . $this->status);
}
public function getAddress()
{
try {
return (new Controller())->getAddressFromGeoPosition($this->lat, $this->lng, 'city');
} catch (Throwable $exception) {
return "";
}
}
public function getArticleCategory()
{
switch ($this->vehicle_type) {
case Car::class:
return 1;
case Motorcycle::class:
return 2;
default:
return null;
}
}
public function isOtherMake(): bool
{
try {
$controller = new Controller();
if ($this->vehicle->make == $controller->getVehicleMakeOtherByVTypeAttr($this->getVehicleType(), 'slug', 'id'))
return true;
return false;
} catch (Throwable $exception) {
return false;
}
}
public function isOtherModel(): bool
{
try {
if ($this->vehicle->model == 0)
return true;
return false;
} catch (Throwable $exception) {
return false;
}
}
public function flushCache()
{
try {
Cache::forget('classified_' . $this->identifier);
Cache::forget('medias_classified_' . $this->identifier);
Cache::remember('classified_' . $this->identifier, 33600, function () {
return $this;
});
Cache::remember('medias_classified_' . $this->identifier, 33600, function () {
return $this->medias()->orderBy('index', 'ASC')->get();
});
} catch (Throwable $exception) {
}
}
public function isProprietor()
{
try {
if (Auth::check()) {
if (session()->has('professional_user') && $this->proprietor_type == Branch::class && $this->proprietor_id == session()->get('professional_user'))
return true;
elseif ($this->proprietor_type == User::class && $this->proprietor_id == Auth::id())
return true;
elseif (Auth::user()->isAdmin())
return true;
}
} catch (Throwable $exception) {
return false;
}
}
public function getFavourites()
{
try {
return $this->favourites->count();
} catch (Throwable $exception) {
return 0;
}
}
public function isMyFavourite(): bool
{
try {
$controller = new Controller();
if ($this->favourites()->where([
'proprietor_id' => $controller->getProprietorId(),
'proprietor_type' => $controller->getProprietorType()
])->count() > 0)
return true;
} catch (Throwable $exception) {
}
return false;
}
public function favourites()
{
return $this->hasMany(ClassifiedFavourite::class);
}
}
store method:
public function store(Request $request): JsonResponse
{
$rules = (new Classified)->rules;
$request->validate($rules['classified']);
$request->validate($rules[$request->input('vehicle_type')]);
DB::beginTransaction();
try {
$vehicleData = $request->all();
$vehicleData['firstRegDate'] = Carbon::createFromFormat('m-Y', $vehicleData['firstRegDate'])->toDateString();
$vehicle = (new Classified())->getVehicleTypeClassByName($request->input('vehicle_type'))::create($vehicleData);
if ($request->has('address'))
$geoData = $this->getGeoPositionFromAddress($request->input('address'));
else
$geoData = (object)[
"lat" => 0,
"lng" => 0
];
$formData = $request->all();
$formData['identifier'] = $this->generateIdentifier();
$formData['proprietor_id'] = $this->getProprietorId();
$formData['proprietor_type'] = $this->getProprietorType();
$formData['lat'] = $geoData->lat;
$formData['lng'] = $geoData->lng;
$formData['video_embed'] = $this->getYoutubeVideoID($request->input('video_embed'));
$formData['status'] = Classified::STATUS_PENDING;
$classified = $vehicle->classified()->create($formData);
$vehicle->classified->price_options()->attach($request->input('price_options'));
$vehicle->classified->features()->attach($request->input('features'));
$vehicle->classified->equipments()->attach($request->input('equipments'));
$medias = json_decode($request->{'fileuploader-list-files'}, true);
foreach ($medias as $media) {
$file = Media::where('name', $media->file)->first();
if ($file) {
$file->mediable_id = $vehicle->classified->id;
$file->saveOrFail();
}
}
if ($formData['proprietor_type'] == User::class && $request->has('phone') && $request->has('address'))
$this->updateUserPhoneAndAddress($formData['phone'], $formData['address']);
$classified->sharing()->create([
'status' => Sharing::STATUS_PENDING,
]);
if ($classified->status == Classified::STATUS_PENDING)
$this->adminAlert($classified);
DB::commit();
toastr()->success("Anúncio submetido para aprovação.");
return response()->json([
'redirect_url' => route('classified.feature', $vehicle->classified->identifier),
]);
} catch (Throwable $exception) {
DB::rollBack();
return response()->json([
'errors' => [trans('custom.error_occurred'), $exception->getMessage()]
], 500);
}
}
Stack Error: https://pastebin.com/jPypBG8P
Anyone has any idea on may be causing this?
Apparently it was the constructor in the Classified Model that was preventing.
A special Thanks to #Tim Lewis !
I am new to ZF2 application. I trying the documentation part as n practice provided in ZF2 doc. Working on album module it is find with the other parts but as it comes to delete. My delete album part is not working and also not showing any error as well
My files for delete code as
//src/Album/Model/AlbumTable.php
namespace Album\Model;
use Zend\Db\TableGateway\TableGateway;
Class AlbumTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway) {
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function getAlbum($id)
{
$id = (int) $id;
$rowset = $this->tableGateway->select(array('id'=> $id));
$row = $rowset->current();
if(!$row)
{
throw new Exception("Could not find row - $id");
}
return $row;
}
public function saveAlbum(Album $album)
{
$data = array(
'artist' => $album->artist,
'title' => $album->title,
);
$id = (int) $album->id;
if($id == 0)
{
$this->tableGateway->insert($data);
}
else
{
if($this->getAlbum($id))
{
$this->tableGateway->update($data, array('id' => $id));
}
else
{
throw new \Exception("Album ID does not exists");
}
}
}
public function deleteAlbum($id)
{
$this->tableGateway->delete(array($id => (int) $this->id));
}
}
Other Album Controller file is as
//src/Album/Controller/AlbumController.php
namespace Album\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Album\Model\Album; // For the Form Display
use Album\Form\AlbumForm; // album manipulation form view
Class AlbumController extends AbstractActionController
{
protected $albumTable;
public function getAlbumTable()
{
if(!$this->albumTable)
{
$sm = $this->getServiceLocator();
$this->albumTable = $sm->get('Album\Model\AlbumTable');
}
return $this->albumTable;
}
public function indexAction()
{
//Albums Retreiving from Model and Passing to View for listing the albums
return new ViewModel(array(
'albums' => $this->getAlbumTable()->fetchAll(),
));
}
public function addAction()
{
$form = new AlbumForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if($request->isPost())
{
$album = new Album();
// printf($form);die();
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if($form->isValid())
{
$album->exchangeArray($form->getData());
$this->getAlbumTable()->saveAlbum($album);
//Redirect to list of albums
$this->redirect()->toRoute('album');
}
}
return array('form' => $form);
}
public function editAction()
{
$id = (int) $this->params()->fromRoute('id',0);
if(!$id)
{
return $this->redirect()->toRoute('album',array(
'action' => 'add'
));
}
// Get the Album with the specified id. An exception is thrown
// if it cannot be found, in which case go to the index page.
try
{
$album = $this->getAlbumTable()->getAlbum($id);
}
catch(\Exception $ex)
{
return $this->redirect()->toRoute('album', array(
'action' => 'index'
));
}
$form = new AlbumForm();
$form->bind($album);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
if($request->isPost())
{
$form->setInputFilter($album->getInputFilter());
$form->setData($request->getPost());
if($form->isValid())
{
$this->getAlbumTable()->saveAlbum($album);
//Redirect to list all albums
return $this->redirect()->toRoute('album');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
public function deleteAction()
{
$id = (int) $this->params()->fromRoute('id',0);
if(!$id)
{
return $this->redirect()->toRoute('album');
}
$request = $this->getRequest();
if($request->isPost())
{
$del = $request->getPost('del','No');
if($del=='Yes')
{
$id = (int)$request->getPost('id');
$this->getAlbumTable()->deleteAlbum($id);
}
//Redirect to list of Albums
return $this->redirect()->toRoute('album');
}
return array(
'id' => $id,
'album' => $this->getAlbumTable()->getAlbum($id),
);
}
}
Deleting File view as follows
//view/album/album/delete.phtml
$title = "Delete Album";
$this->headTitle($title);
?>
<h1><?php echo $this->escapeHtml($title); ?></h1>
<p>
Are you sure want to delete the album
'<?php echo $this->escapeHtml($album->title); ?>' By
'<?php echo $this->escapeHtml($album->artist); ?>' ??
</p>
<?php
$url = $this->url('album', array(
'action' => 'delete',
'id' => $this->id,
));
?>
<form action='<?php echo $url; ?>' method='post'>
<div>
<input type='hidden' name='id' value='<?php echo (int)$album->id; ?>'/>
<input type='submit' name='del' value='Yes'/>
<input type="submit" name="del" value='No'/>
</div>
</form>
When i'm trying to delete the album it askes for confirmation and when pressed as yes it get to album lists again showing the same record within the lists.
Maybe you are having problem with the first files itself for delete operation
In your //src/Album/Model/AlbumTable.php file
You stated the deleteAlbum function as
public function deleteAlbum($id)
{
$this->tableGateway->delete(array($id => (int) $this->id));
}
Rewrite the code as
public function deleteAlbum($id)
{
$this->tableGateway->delete(array('id' => (int) $id));
}
Hopefullly this was the only problem as you said it doesn't showing any error or at least exception.
I am super new to doctrine and I just converted the Akrabat album rest api example to work with doctrine and it works well to show the data. But when i edit, delete or add albums it throws an error which says,
Fatal error: Call to undefined method Zend\Http\PhpEnvironment\Request::post()
Here's is my controller,
namespace Album\Controller;
use Zend\Mvc\Controller\AbstractActionController,
Zend\View\Model\ViewModel,
Album\Form\AlbumForm,
Doctrine\ORM\EntityManager,
Album\Entity\Album;
class AlbumController extends AbstractActionController
{
protected $em;
public function setEntityManager(EntityManager $em)
{
$this->em = $em;
}
public function getEntityManager()
{
if (null === $this->em) {
$this->em = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
}
return $this->em;
}
public function indexAction()
{
return new ViewModel(array(
'albums' => $this->getEntityManager()->getRepository('Album\Entity\Album')->findAll()
));
}
public function addAction()
{
$form = new AlbumForm();
$form->get('submit')->setAttribute('label', 'Add');
$request = $this->getRequest();
if ($request->isPost()) {
$album = new Album();
$form->setInputFilter($album->getInputFilter());
$form->setData($request->post());
if ($form->isValid()) {
$album->populate($form->getData());
$this->getEntityManager()->persist($album);
$this->getEntityManager()->flush();
// Redirect to list of albums
return $this->redirect()->toRoute('album');
}
}
return array('form' => $form);
}
public function editAction()
{
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('album', array('action'=>'add'));
}
$album = $this->getEntityManager()->find('Album\Entity\Album', $id);
$form = new AlbumForm();
$form->setBindOnValidate(false);
$form->bind($album);
$form->get('submit')->setAttribute('label', 'Edit');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->post());
if ($form->isValid()) {
$form->bindValues();
$this->getEntityManager()->flush();
// Redirect to list of albums
return $this->redirect()->toRoute('album');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
public function deleteAction()
{
$id = (int)$this->getEvent()->getRouteMatch()->getParam('id');
if (!$id) {
return $this->redirect()->toRoute('album');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->post()->get('del', 'No');
if ($del == 'Yes') {
$id = (int)$request->post()->get('id');
$album = $this->getEntityManager()->find('Album\Entity\Album', $id);
if ($album) {
$this->getEntityManager()->remove($album);
$this->getEntityManager()->flush();
}
}
// Redirect to list of albums
return $this->redirect()->toRoute('default', array(
'controller' => 'album',
'action' => 'index',
));
}
return array(
'id' => $id,
'album' => $this->getEntityManager()->find('Album\Entity\Album', $id)->getArrayCopy()
);
}
}
What am i doing wrong here, I am not able to persist any changes that i make.
Because there's no post method. Try getPost(); see here Zend\Http\Request
I'm having issues trying to unit test an action which uses ZfcUser for authentication. I need some way to mock the ZfcUser Controller plugin but I'm not so sure how to do this. I've managed to successfully produce some unit tests for tables and models but the controller requires a lot of injected objects and is causing problems. Does anyone know how to set up the ZfcUser mocks to successfully unit test a controller?
Here is my test (copied from the ZF2 tutorial):
<?php
namespace SmsTest\Controller;
use SmsTest\Bootstrap;
use Sms\Controller\SmsController;
use Zend\Http\Request;
use Zend\Http\Response;
use Zend\Mvc\MvcEvent;
use Zend\Mvc\Router\RouteMatch;
use Zend\Mvc\Router\Http\TreeRouteStack as HttpRouter;
use PHPUnit_Framework_TestCase;
class SmsControllerTest extends PHPUnit_Framework_TestCase
{
protected $controller;
protected $request;
protected $response;
protected $routeMatch;
protected $event;
protected function setUp()
{
$serviceManager = Bootstrap::getServiceManager();
$this->controller = new SmsController();
$this->request = new Request();
$this->routeMatch = new RouteMatch(array('controller' => 'index'));
$this->event = new MvcEvent();
$config = $serviceManager->get('Config');
$routerConfig = isset($config['router']) ? $config['router'] : array();
$router = HttpRouter::factory($routerConfig);
$this->event->setRouter($router);
$this->event->setRouteMatch($this->routeMatch);
$this->controller->setEvent($this->event);
$this->controller->setServiceLocator($serviceManager);
}
/* Test all actions can be accessed */
public function testIndexActionCanBeAccessed()
{
$this->routeMatch->setParam('action', 'index');
$result = $this->controller->dispatch($this->request);
$response = $this->controller->getResponse();
$this->assertEquals(200, $response->getStatusCode());
}
}
I tried the following in the setUp method:
$mockAuth = $this->getMock('ZfcUser\Entity\UserInterface');
$authMock = $this->getMock('Zend\Authentication\AuthenticationService');
$authMock->expects($this->any())
->method('hasIdentity')
->will($this->returnValue(true));
$authMock->expects($this->any())
->method('getIdentity')
->will($this->returnValue(array('user_id' => 1)));
But I'm not sure how to inject this in to the controller instance.
Lets pretend my index action code is just as follows:
public function indexAction() {
//Check if logged in
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('zfcuser/login');
}
return new ViewModel(array(
'success' => true,
));
}
Test Results:
1) SmsTest\Controller\SmsControllerTest::testIndexActionCanBeAccessed
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php:450
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/ServiceManager/AbstractPluginManager.php:110
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/PluginManager.php:90
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:276
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:291
/var/www/soap-app.localhost/Zend/module/Sms/src/Sms/Controller/SmsController.php:974
/var/www/soap-app.localhost/Zend/module/Sms/src/Sms/Controller/SmsController.php:974
/var/www/soap-app.localhost/Zend/module/Sms/src/Sms/Controller/SmsController.php:158
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractActionController.php:87
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:468
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/EventManager/EventManager.php:208
/var/www/soap-app.localhost/Zend/vendor/zendframework/zendframework/library/Zend/Mvc/Controller/AbstractController.php:108
/var/www/soap-app.localhost/Zend/module/Sms/test/SmsTest/Controller/SmsControllerTest.php:57
The line which causes this exception is the controller is: if (!$this->zfcUserAuthentication()->hasIdentity()) {
That line relates to line 974 in the SmsController.
It's obvious I don't have access to the ZfcUserAuthentication service, so the question is, How do I mock the ZfcUserAuthentication service and inject it in to my Controller?
To continue the theme how would I go about mocking a logged in user to successfully test my action is working to specification?
The ZfcUser documentation suggests that this is a plugin so you need to inject this into the controller.
You will need to amend your class names to pick up the ZfcUser classes
Your mocks will also need to be addapted as getIdenty returns a different object.
The following worked for me - insert in your phpunit setUp() method.
$serviceManager = Bootstrap::getServiceManager();
$this->controller = new RegisterController();
$this->request = new Request();
$this->routeMatch = new RouteMatch(array('controller' => 'add'));
$this->event = new MvcEvent();
$config = $serviceManager->get('Config');
$routerConfig = isset($config['router']) ? $config['router'] : array();
$router = HttpRouter::factory($routerConfig);
$this->event->setRouter($router);
$this->event->setRouteMatch($this->routeMatch);
$this->controller->setEvent($this->event);
$this->controller->setServiceLocator($serviceManager);
$mockAuth = $this->getMock('ZfcUser\Entity\UserInterface');
$ZfcUserMock = $this->getMock('ZfcUser\Entity\User');
$ZfcUserMock->expects($this->any())
->method('getId')
->will($this->returnValue('1'));
$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication');
$authMock->expects($this->any())
->method('hasIdentity')
-> will($this->returnValue(true));
$authMock->expects($this->any())
->method('getIdentity')
->will($this->returnValue($ZfcUserMock));
$this->controller->getPluginManager()
->setService('zfcUserAuthentication', $authMock);
There may be an easier way would welcome other thoughts.
This is how I did it.
<?php
namespace IssueTest\Controller;
use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase;
class IssueControllerTest extends AbstractHttpControllerTestCase
{
protected $serviceManager;
public function setUp()
{
$this->setApplicationConfig(
include '/media/policybubble/config/application.config.php'
);
parent::setUp();
$ZfcUserMock = $this->getMock('ZfcUser\Entity\User');
$ZfcUserMock->expects($this->any())
->method('getId')
->will($this->returnValue('1'));
$authMock = $this->getMock(
'ZfcUser\Controller\Plugin\ZfcUserAuthentication'
);
$authMock->expects($this->any())
->method('hasIdentity')
->will($this->returnValue(true));
$authMock->expects($this->any())
->method('getIdentity')
->will($this->returnValue($ZfcUserMock));
$this->serviceManager = $this->getApplicationServiceLocator();
$this->serviceManager->setAllowOverride(true);
$this->serviceManager->get('ControllerPluginManager')->setService(
'zfcUserAuthentication', $authMock
);
}
public function testIndexActionCanBeAccessed()
{
$this->dispatch('/issue');
$this->assertResponseStatusCode(200);
$this->assertModuleName('Issue');
$this->assertControllerName('Issue\Controller\Issue');
$this->assertControllerClass('IssueController');
$this->assertMatchedRouteName('issue');
}
public function testAddActionRedirectsAfterValidPost()
{
$issueTableMock = $this->getMockBuilder('Issue\Model\IssueTable')
->disableOriginalConstructor()
->getMock();
$issueTableMock->expects($this->once())
->method('saveIssue')
->will($this->returnValue(null));
$this->serviceManager->setService('Issue\Model\IssueTable', $issueTableMock);
$postData = array(
'title' => 'Gun Control',
'id' => '',
);
$this->dispatch('/issue/add', 'POST', $postData);
$this->assertResponseStatusCode(302);
$this->assertRedirectTo('/issue');
}
public function testEditActionRedirectsAfterValidPost()
{
$issueTableMock = $this->getMockBuilder('Issue\Model\IssueTable')
->disableOriginalConstructor()
->getMock();
$issueTableMock->expects($this->once())
->method('saveIssue')
->will($this->returnValue(null));
$this->serviceManager->setService('Issue\Model\IssueTable', $issueTableMock);
$issueTableMock->expects($this->once())
->method('getIssue')
->will($this->returnValue(new \Issue\Model\Issue()));
$postData = array(
'title' => 'Gun Control',
'id' => '1',
);
$this->dispatch('/issue/edit/1', 'POST', $postData);
$this->assertResponseStatusCode(302);
$this->assertRedirectTo('/issue');
}
public function testDeleteActionRedirectsAfterValidPost()
{
$postData = array(
'title' => 'Gun Control',
'id' => '1',
);
$this->dispatch('/issue/delete/1', 'POST', $postData);
$this->assertResponseStatusCode(302);
$this->assertRedirectTo('/issue');
}
}
<?php
namespace Issue\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Issue\Model\Issue;
use Issue\Form\IssueForm;
class IssueController extends AbstractActionController
{
protected $issueTable;
public function indexAction()
{
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return;
}
return new ViewModel(
array(
'issues' => $this->getIssueTable()->fetchAll(
$this->zfcUserAuthentication()->getIdentity()->getId()
),
)
);
}
public function addAction()
{
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('issue');
}
$form = new IssueForm();
$form->get('submit')->setValue('Add');
$request = $this->getRequest();
if ($request->isPost()) {
$issue = new Issue();
$form->setInputFilter($issue->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$issue->exchangeArray($form->getData());
$this->getIssueTable()->saveIssue(
$issue,
$this->zfcUserAuthentication()->getIdentity()->getId()
);
// Redirect to list of issues
return $this->redirect()->toRoute('issue');
}
}
return array('form' => $form);
}
public function editAction()
{
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('issue');
}
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute(
'issue', array(
'action' => 'add'
)
);
}
// Get the Issue with the specified id. An exception is thrown
// if it cannot be found, in which case go to the index page.
try {
$issue = $this->getIssueTable()->getIssue($id);
} catch (\Exception $ex) {
return $this->redirect()->toRoute(
'issue', array(
'action' => 'index'
)
);
}
$form = new IssueForm();
$form->bind($issue);
$form->get('submit')->setAttribute('value', 'Edit');
$request = $this->getRequest();
if ($request->isPost()) {
$form->setInputFilter($issue->getInputFilter());
$form->setData($request->getPost());
if ($form->isValid()) {
$this->getIssueTable()->saveIssue(
$issue,
$this->zfcUserAuthentication()->getIdentity()->getId()
);
// Redirect to list of issues
return $this->redirect()->toRoute('issue');
}
}
return array(
'id' => $id,
'form' => $form,
);
}
public function deleteAction()
{
if (!$this->zfcUserAuthentication()->hasIdentity()) {
return $this->redirect()->toRoute('issue');
}
$id = (int)$this->params()->fromRoute('id', 0);
if (!$id) {
return $this->redirect()->toRoute('issue');
}
$request = $this->getRequest();
if ($request->isPost()) {
$del = $request->getPost('del', 'No');
if ($del == 'Yes') {
$id = (int)$request->getPost('id');
$this->getIssueTable()->deleteIssue($id);
}
// Redirect to list of issues
return $this->redirect()->toRoute('issue');
}
return array(
'id' => $id,
'issue' => $this->getIssueTable()->getIssue($id)
);
}
public function getIssueTable()
{
if (!$this->issueTable) {
$sm = $this->getServiceLocator();
$this->issueTable = $sm->get('Issue\Model\IssueTable');
}
return $this->issueTable;
}
}