Problem With Getting Started Database CRUD Example - yii

I have been working through the getting started guide for Yii. After generating the CRUD code I receive an error when clicking on the "View/Edit/Delete" buttons. It appears that the generated links are incorrect in that they reference "id" rather than "code" (which is the primary key).
E.g the View link is
http://localhost/yii/demo/basic/web/index.php?r=country%2Fview&id=AU
which generates the error
Bad Request (#400)
Missing required parameters: code
when I manually change the link to
http://localhost/yii/demo/basic/web/index.php?r=country%2Fview&code=AU
it works correctly. Why is it referencing "id"?
I also had to modify the CountryController.php file, findModel function which was again referencing "id"
if (($model = Country::findOne($id)) !== null) {
when changed to "code" this worked.
protected function findModel($code)
{
if (($model = Country::findOne($code)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
Does anyone have any ideas, the db is MySQL and the Code column is defined as the Primary Key.

This is a bug in the current yii code.
It expects ID to be the primary key always
A way of fixing it would be to remove the action column from the gridview in index.php and add
[
'class' => 'yii\grid\ActionColumn',
'header' => 'Actions',
'headerOptions' => ['style' => 'color:#337ab7'],
'template' => '{view}{update}{delete}',
'urlCreator' => function ($action, $model, $key, $index) {
if ($action === 'view') {
$url ='index.php?r=country/view&code='.$model->code;
return $url;
}
if ($action === 'update') {
$url ='index.php?r=country/update&code='.$model->code;
return $url;
}
if ($action === 'delete') {
$url ='index.php?r=country/delete&code='.$model->code;
return $url;
}
}
],
Just got done going through old answers regarding how to change gridview to get to this.

Related

Yii2 - Bad Request (#400) Missing required parameters in index.php

I have problem for action view, update, and delete in index.php page, it always show bad request (#400) Missing required parameters: id_kategori and the address always go to localhost/training/frontend/web/index.php?r=kategori%2F(view/update/delete)&id=1, but when i change the address manually to localhost/training/frontend/web/index.php?r=kategori%2Fview&id_kategori=1 it's no problem, also i can create action but then it will redirect page to localhost/training/frontend/web/index.php?r=kategori%2Fview&id=1. Here's the code, its generate from Gii CRUD:
public function actionView($id_kategori)
{
return $this->render('view', [
'model' => $this->findModel($id_kategori),
]);
}
public function actionUpdate($id_kategori)
{
$model = $this->findModel($id_kategori);
if ($this->request->isPost && $model->load($this->request->post()) && $model->save()) {
return $this->redirect(['view', 'id_kategori' => $model->id_kategori]);
}
return $this->render('update', [
'model' => $model,
]);
}
public function actionDelete($id_kategori)
{
$this->findModel($id_kategori)->delete();
return $this->redirect(['index']);
}
Should i rename id_kategori column to id and other id_column just to id?
Version: Yii 2 (2.0.43)
Template: Advanced Template
define $id_kategori=null in function
public function actionView($id_kategori=null)
{
return $this->render('view', [
'model' => $id_kategori ? $this->findModel($id_kategori) : null,
]);
}
You need to do like this
public function actionView($id) {
return $this->render('view', [
'model' => $this->findModel($id),
]);
}

Laravel 5.6 - creation user not working

my application used to working well with registration user but now it dont.
here a portion of my model User
protected $fillable = [
'prenom', 'nom', 'email','photo_path','password',
];
here my validation function :
protected function validator(array $data)
{
return Validator::make($data, [
'prenom' => 'required|string|max:255',
'nom' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'photo_path' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:10000',
'password' => 'required|string|min:6|confirmed',
]);
}
here my create function :
protected function create(array $data)
{
dd($data);
$photoInput = request('photo_path');
$userPhotoPath='users';
$storagePhotoPath = Storage::disk('images')->put($userPhotoPath, $photoInput);
return User::create([
'prenom' => $data['prenom'],
'nom' => $data['nom'],
'email' => $data['email'],
'photo_path' => $storagePhotoPath,
'password' => Hash::make($data['password']),
]);
}
- POST request working ( return 302 ) but return back with input value
- Auth Route are declared in web.php
- Validation working well
but the php interpretor didnt get inside create function...
i just see in debugbar that information :
The given data was invalid./home/e7250/Laravel/ManageMyWorkLife/vendor/laravel/framework/src/Illuminate/Validation/Validator.php#306Illuminate\Validation\ValidationException
public function validate()
{
if ($this->fails()) {
throw new ValidationException($this);
}
$data = collect($this->getData())
but my validation working because i have error message near my InputTexte.
so i dont understand that error message ...
Do you have any clue ?
Well, you need to remove the dd(); function before you run something. Other wise it will end the execution of all other operations.
Check if your User Model has a constructor, if so remove it and check if the problem still accours. This fixed it for me.

Insert in yii2 from different controller

I am tring to insert data in a table.
trying like this but it`s not working.
$sql = $queryBuilder->insert(' HRMS_candidateEducation', [
'HRMS_candidateEducationCandidateID' => $candidateID,
'HRMS_candidateEducationDegree' => $data['Degree'.$i],
'HRMS_candidateEducationUniversity' => $data['University'.$i],
'HRMS_candidateEducationCollege' => $data['College'.$i],
'HRMS_candidateEducationYear' => $data['Specilization'.$i],
'HRMS_candidateEducationSpecilization' => $data['Specilization'.$i],
], $params);
What is incorrect?
using
use yii\db\QueryBuilder;
use app\models\CandidateEducation;
This function seem only create the SQL statement see doc
insert() Creates an INSERT command
for executing the command i think you shoul try this way
Yii::$app->db->createCommand()->
insert(' HRMS_candidateEducation', [
'HRMS_candidateEducationCandidateID' => $candidateID,
'HRMS_candidateEducationDegree' => $data['Degree'.$i],
'HRMS_candidateEducationUniversity' => $data['University'.$i],
'HRMS_candidateEducationCollege' => $data['College'.$i],
'HRMS_candidateEducationYear' => $data['Specilization'.$i],
'HRMS_candidateEducationSpecilization' => $data['Specilization'.$i],
], $params)->
execute();
I found another solution to my question.
This is what i did. by following this link.
public function actionCreate()
{
$a=new A;
$b=new B;
if(isset($_POST['A'], $_POST['B']))
{
// populate input data to $a and $b
$a->attributes=$_POST['A'];
$b->attributes=$_POST['B'];
// validate BOTH $a and $b
$valid=$a->validate();
$valid=$b->validate() && $valid;
if($valid)
{
// use false parameter to disable validation
$a->save(false);
$b->save(false);
// ...redirect to another page
}
}
$this->render('create', array(
'a'=>$a,
'b'=>$b,
));
}

ZF2 / doctrine ORM authentication different Entity

in my application (ZF2 / ORM) i have 3 Entities (with Single Table inheritance)
User
Owner extends User
Agent extends User
i want to make one single Authentication (Login) for the 3 Entity using
doctrine.authenticationservice.orm_default
module.config.php
//other doctrine config
'authentication' => array(
'orm_default' => array(
'object_manager' => 'Doctrine\ORM\EntityManager',
'identity_class' => 'Application\Entity\User',
'identity_property' => 'email',
'credential_property' => 'password',
'credential_callable' => function(User $user, $passwordGiven) {
return $user->getPassword() == md5($passwordGiven);
},
),
),
and the process of login
//LoginController.php
// ..data validation
$this->authService = $this->getServiceLocator()->get('doctrine.authenticationservice.orm_default');
$AuthAdapter = $this->authService->getAdapter();
$AuthAdapter->setIdentity($this->request->getPost('email'));
$AuthAdapter->setCredential(md5($this->request->getPost('password')));
$result = $this->authService->authenticate();
if($result->isValid()){
$identity = $result->getIdentity();
//continue
}
how can i do this process without caring about object type,
when i try to login with email of an Agent, i get this error
Catchable fatal error: Argument 1 passed to Application\Module::{closure}() must be an instance of User, instance of Application\Entity\Owner given
The error you mention is due to the type hint on:
function(User $user) {
Which leads me to believe that you have a missing namespace declaration in your config file; in which case you can either add it or use the FQCN.
function(\Application\Entity\User $user) {
Nevertheless, I don't think it's actually the problem. You can only define one 'identity_class' with doctrine authentication (which the adapter will use to load the entity from the entity manager). If you have multiple entity classes there is no way to have each of these tested with one adapter.
However, the configuration is really just creating a new authentication adapter, specifically DoctrineModule\Authentication\Adapter\ObjectRepository. One solution would be to create multiple ObjectRepository adapters, each with the correct configuration for the different entities and then loop through each of them while calling authenticate() on the Zend\Authentication\AuthenticationService.
For example :
public function methodUsedToAutheticate($username, $password)
{
// Assume we have an array of configured adapters in an array
foreach($adapters as $adapter) {
$adapter->setIdentity($username);
$adapter->setCredential($password);
// Authenticate using the new adapter
$result = $authService->authenticate($adapter);
if ($result->isValid()) {
// auth success
break;
}
}
return $result; // auth failed
}
As previously mentioned is the doctrine config will not allow for more than one adapter, so you would need to create them manually and remove your current configuration.
Another example
public function getServiceConfig()
{
return [
'factories' => [
'MyServiceThatDoesTheAuthetication' => function($sm) {
$service = new MyServiceThatDoesTheAuthetication();
// Assume some kind of api to add multiple adapters
$service->addAuthAdapter($sm->get('AuthAdapterUser'));
$service->addAuthAdapter($sm->get('AuthAdapterOwner'));
$service->addAuthAdapter($sm->get('AuthAdapterAgent'));
return $service;
},
'AuthAdapterAgent' => function($sm) {
return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
'object_manager' => $sm->get('ObjectManager'),
'identity_class' => 'Application\Entity\Agent',
'identity_property' => 'email',
'credential_property' => 'password'
));
},
'AuthAdapterOwner' => function($sm) {
return new DoctrineModule\Authentication\Adapter\ObjectRepository(array(
'object_manager' => $sm->get('ObjectManager'),
'identity_class' => 'Application\Entity\Owner',
'identity_property' => 'email',
'credential_property' => 'password'
));
},
// etc...
],
];
}
Hopefully this gives you some ideas as to what is required.
Lastly, if you would consider other modules, ZfcUser already has a 'chainable adapter' which actually does the above (but uses the event manager) so It might be worth taking a look at even if you don't use it.

How can I use custom exception pages with ZF2?

I need to redirect a user to an error page (view/error/403.phtml) from within the Module.php of a module called Admin when a user is not allowed to access the specific resource. I have been searching for a solution to this, but so far had no success. The best I found was this question, the accepted answer to which doesn't work for me (and I currently cannot add comments to the linked question because I don't have the required reputation level) - the page is displayed as if there is no redirect at all and the user is allowed to access it. I have tried to replace the redirecting code with a simple die; to test if the isAllowed() is working properly, and it correctly shows a blank page, so the problem lies in the redirection itself.
Relevant code in Module.php is:
public function onBootstrap(MvcEvent $e)
{
$this->initAcl($e);
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach('route', array($this, 'checkAcl'));
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
public function checkAcl(MvcEvent $e)
{
// ...
if (!$this->acl->isAllowed($userRole, $controller, $privilege))
{
$response = $e->getResponse();
$response->setHeaders($response->getHeaders()->addHeaderLine('Location', $e->getRequest()->getBaseurl() . '/error/403'));
$response->setStatusCode(403);
$response->sendHeaders();
}
// ...
}
module.config.php
'view_manager' => array(
'display_exceptions' => true,
'exception_template' => 'error/403',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/admin_layout.phtml',
'error/403' => __DIR__ . '/../view/error/403.phtml',
'error/404' => __DIR__ . '/../view/error/404.phtml',
'error/index' => __DIR__ . '/../view/error/index.phtml',
),
'template_path_stack' => array(
'Admin' => __DIR__ . '/../view',
),
'strategies' => array(
'ViewJsonStrategy',
),
),
If I add the line
throw new \Exception($translator->translate('Access denied'));
after the code for redirection, I do get redirected to URL http://[servername]/error/403, but the contents of the page is, instead of my custom 403.phtml, a styled (with layout) 404 error page, stating that "The requested URL could not be matched by routing."
A better way to achieve what you want is to trigger a dispatch.error event in your checkAcl function rather than trying to do a redirect. You can then handle this event and display the 403 page.
To trigger the event:
if (!$this->acl->isAllowed($userRole, $controller, $privilege))
{
$app = $e->getTarget();
$route = $e->getRouteMatch();
$e->setError('ACL_ACCESS_DENIED') // Pick your own value, would be better to use a const
->setParam('route', $route->getMatchedRouteName());
$app->getEventManager()->trigger('dispatch.error', $e);
}
Then in your onBootstrap add a listener for the dispatch.error event:
use Zend\Mvc\MvcEvent;
...
$eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, <any callable>, -999);
In your callback for dispatch.error event you just attached to:
$error = $event->getError();
if (empty($error) || $error != "ACL_ACCESS_DENIED") {
return;
}
$result = $event->getResult();
if ($result instanceof StdResponse) {
return;
}
$baseModel = new ViewModel();
$baseModel->setTemplate('layout/layout');
$model = new ViewModel();
$model->setTemplate('error/403');
$baseModel->addChild($model);
$baseModel->setTerminal(true);
$event->setViewModel($baseModel);
$response = $event->getResponse();
$response->setStatusCode(403);
$event->setResponse($response);
$event->setResult($baseModel);
return false;