Somehow I can't trace what is wrong with my codes. I'm trying to display a typ_name instead of id, so I defined the following relationship in both type and infrastructure models but I can't able to display the name.
Models codes shown below
type.php
<?php
namespace App\Models;
use Eloquent as Model;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class type
* #package App\Models
* #version January 16, 2020, 4:01 am UTC
*
* #property string typ_name
*/
class type extends Model
{
use SoftDeletes;
public $table = 'types';
protected $dates = ['deleted_at'];
public $fillable = [
'typ_name'
];
public function type()
{
return $this->hasMany('infrastructure');
}
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'id' => 'integer',
'typ_name' => 'string'
];
/**
* Validation rules
*
* #var array
*/
public static $rules = [
'typ_name' => 'required'
];
}
infrastructure.php
<?php
namespace App\Models;
use Eloquent as Model;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class infrastructure
* #package App\Models
* #version January 23, 2020, 1:44 am UTC
*
* #property string inf_name
* #property integer inf_height
* #property integer inf_width
* #property integer typ_id
* #property integer island_id
* #property integer engnr_id
* #property integer designer_id
* #property integer foreman_id
* #property string start_date
* #property string cmplt_date
* #property string inf_lifspan
* #property string inf_file
* #property integer inf_lat
* #property integer inf_long
* #property string inf_comment
*/
class infrastructure extends Model
{
use SoftDeletes;
public $table = 'infrastructures';
protected $dates = ['deleted_at'];
public $fillable = [
'inf_name',
'inf_height',
'inf_width',
'inf_length',
'typ_id',
'island_id',
'engnr_id',
'designer_id',
'foreman_id',
'start_date',
'cmplt_date',
'inf_lifspan',
'inf_file',
'inf_lat',
'inf_long',
'inf_comment'
];
/**
* Get the type record associated with the Infrastructure.
*/
public function type()
{
return $this->belongsTo('type', 'typ_id', 'id');
}
/**
* The attributes that should be casted to native types.
*
* #var array
*/
protected $casts = [
'id' => 'integer',
'inf_name' => 'string',
'inf_height' => 'integer',
'inf_width' => 'integer',
'inf_length' => 'integer',
'typ_id' => 'integer',
'island_id' => 'integer',
'engnr_id' => 'integer',
'designer_id' => 'integer',
'foreman_id' => 'integer',
'start_date' => 'date',
'cmplt_date' => 'date',
'inf_lifspan' => 'date',
'inf_lat' => 'double',
'inf_long' => 'double',
'inf_comment' => 'string'
];
/**
* Validation rules
*
* #var array
*/
public static $rules = [
'inf_name' => 'required',
'inf_height' => 'required',
'inf_width' => 'required',
'inf_length' => 'required',
'typ_id' => 'required',
'island_id' => 'required',
'engnr_id' => 'required',
'designer_id' => 'required',
'foreman_id' => 'required',
'start_date' => 'required',
'cmplt_date' => 'required',
'inf_lifspan' => 'required',
'inf_file' => 'required',
'inf_lat' => 'required',
'inf_long' => 'required',
'inf_comment' => 'required'
];
}
infrastructureController.php
public function show($id)
{
$infrastructure = $this->infrastructureRepository->find($id);
if (empty($infrastructure)) {
Flash::error('Infrastructure not found');
return redirect(route('infrastructures.index'));
}
return view('infrastructures.show')->with('infrastructure', $infrastructure);
}
In my blade.php
<!-- Typ Id Field -->
<div class="form-group">
{!! Form::label('typ_id', 'Type:') !!}
{{ $infrastructure->type->typ_name }}
</div>
I think you defined your relation wrong in your infrastructure.php.
Should be
public function type()
{
return $this->belongsTo(type::class, 'typ_id');
}
typ_id being your foreign key in your infrastructures (?) table
Also, don't forget to adjust your type.php
public function type()
{
return $this->hasMany(infrastructure::class);
}
Related
While editing a user in CakePHP 4, I want to validate the fields 'password' and 'password_check' only when the 'password' field is not empty.
When 'password' is not empty, those validation rules should be active:
'password' should count at least 8 characters.
'password' should count at most 60 characters.
'password_check' should be required.
'password_check' should count at least 8 characters.
'password_check' should count at most 60 characters.
'password_check should be identical to 'password'.
In UsersController.php, I tried to remove the 'password' value out of the request data so it's not validated when the entity is patched, but apperently that's not possible:
if (empty($this->request->getData('password'))) {
unset($this->request->getData('password')); // error: can't use method return value in write context
unset($this->request->getData('password_check')); // error: can't use method return value in write context
};
$user = $this->Users->patchEntity($user, $this->request->getData()); // validator is called here
Can somebody guide me the way so my preferred validation happens in an efficient way?
Thanks a lot!
Oh yes, here's my UsersTable.php code:
<?php
declare(strict_types=1);
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Users Model
*
* #property \App\Model\Table\LanguagesTable&\Cake\ORM\Association\BelongsTo $Languages
* #property \App\Model\Table\RolesTable&\Cake\ORM\Association\BelongsTo $Roles
* #property \App\Model\Table\ArticleCategoriesTable&\Cake\ORM\Association\HasMany $ArticleCategories
* #property \App\Model\Table\ArticleImagesTable&\Cake\ORM\Association\HasMany $ArticleImages
* #property \App\Model\Table\ArticleTagsTable&\Cake\ORM\Association\HasMany $ArticleTags
* #property \App\Model\Table\ArticlesTable&\Cake\ORM\Association\HasMany $Articles
* #property \App\Model\Table\CategoriesTable&\Cake\ORM\Association\HasMany $Categories
* #property \App\Model\Table\LinksTable&\Cake\ORM\Association\HasMany $Links
* #property \App\Model\Table\MenusTable&\Cake\ORM\Association\HasMany $Menus
* #property \App\Model\Table\ModulePartsTable&\Cake\ORM\Association\HasMany $ModuleParts
* #property \App\Model\Table\ModulesTable&\Cake\ORM\Association\HasMany $Modules
* #property \App\Model\Table\PagesTable&\Cake\ORM\Association\HasMany $Pages
* #property \App\Model\Table\PartsTable&\Cake\ORM\Association\HasMany $Parts
* #property \App\Model\Table\TagsTable&\Cake\ORM\Association\HasMany $Tags
*
* #method \App\Model\Entity\User newEmptyEntity()
* #method \App\Model\Entity\User newEntity(array $data, array $options = [])
* #method \App\Model\Entity\User[] newEntities(array $data, array $options = [])
* #method \App\Model\Entity\User get($primaryKey, $options = [])
* #method \App\Model\Entity\User findOrCreate($search, ?callable $callback = null, $options = [])
* #method \App\Model\Entity\User patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* #method \App\Model\Entity\User[] patchEntities(iterable $entities, array $data, array $options = [])
* #method \App\Model\Entity\User|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
* #method \App\Model\Entity\User saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
* #method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface|false saveMany(iterable $entities, $options = [])
* #method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface saveManyOrFail(iterable $entities, $options = [])
* #method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface|false deleteMany(iterable $entities, $options = [])
* #method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface deleteManyOrFail(iterable $entities, $options = [])
*
* #mixin \Cake\ORM\Behavior\TimestampBehavior
*/
class UsersTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config): void
{
parent::initialize($config);
$this->setTable('users');
$this->setDisplayField('username');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Languages', [
'foreignKey' => 'language_id',
'joinType' => 'INNER',
]);
$this->belongsTo('Roles', [
'foreignKey' => 'role_id',
'joinType' => 'INNER',
]);
$this->hasMany('ArticleCategories', [
'foreignKey' => 'user_id',
]);
$this->hasMany('ArticleImages', [
'foreignKey' => 'user_id',
]);
$this->hasMany('ArticleTags', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Articles', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Categories', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Links', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Menus', [
'foreignKey' => 'user_id',
]);
$this->hasMany('ModuleParts', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Modules', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Pages', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Parts', [
'foreignKey' => 'user_id',
]);
$this->hasMany('Tags', [
'foreignKey' => 'user_id',
]);
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator): Validator
{
$validator
->scalar('first_name', __('Valid first_name is required.'))
->maxLength('first_name', 30, __('First name should count at most 30 characters.'))
->requirePresence('first_name', 'create')
->notEmptyString('first_name', __('First name is required.'));
$validator
->scalar('last_name', __('Valid last name is required.'))
->maxLength('last_name', 30, __('Last name should count at most 30 characters.'))
->requirePresence('last_name', 'create')
->notEmptyString('last_name', __('Last name is required.'));
$validator
->scalar('username', __('Valid username is required.'))
->maxLength('username', 30, __('Username should count at most 30 characters.'))
->requirePresence('username', 'create')
->notEmptyString('username', __('Username is required.'));
$validator
->email('email', true, __('Valid email is required.'))
->requirePresence('email', 'create')
->notEmptyString('email', __('Email is required.'));
$validator
->scalar('password', __('Valid password is required.'))
->minLength('password', 8, __('Password should count at least 8 characters.'))
->maxLength('password', 60, __('Password should count at most 60 characters.'))
->requirePresence('password', 'create')
->notEmptyString('password', __('Password is required.'));
$validator
->scalar('password_check', __('Password check is required.'))
->minLength('password_check', 8, __('Password check should count at least 8 characters.'))
->maxLength('password_check', 60, __('Password check should count at most 60 characters.'))
->requirePresence('password_check', 'create')
->notEmptyString('password_check', __('Password check is required.'))
->sameAs('password_check', 'password', __('Password check and password should be identical.'));
$validator
->integer('role_id', __('Valid role is required.'))
->notEmptyString('role_id', __('Role is required.'));
$validator
->boolean('is_active', __('Valid is active is required.'))
->notEmptyString('is_active', __('Is active is required.'));
$validator
->integer('language_id', __('Valid language is required.'))
->notEmptyString('language_id', __('Language is required.'));
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* #param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* #return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules): RulesChecker
{
$rules->add($rules->isUnique(['username']), ['errorField' => 'username']);
$rules->add($rules->isUnique(['email']), ['errorField' => 'email']);
$rules->add($rules->existsIn('role_id', 'Roles'), ['errorField' => 'role_id']);
$rules->add($rules->existsIn('language_id', 'Languages'), ['errorField' => 'language_id']);
return $rules;
}
}
There are exceptions, but usually when you feel the need to modify the data in the actual request object, you're most likely doing something wrong.
The intended way to modify (request) data before marshalling when creating/patching entities, is the beforeMarshal event/callback.
// in `UsersTable` class
public function beforeMarshal(
\Cake\Event\EventInterface $event,
\ArrayAccess $data,
\ArrayObject $options
): void {
if (empty($data['password'])) {
unset($data['password']);
}
if (empty($data['password_check'])) {
unset($data['password_check']);
}
}
See also
Cookbook > Database Access & ORM > Saving Data > Modifying Request Data Before Building Entities
I got the following error when I try to write $fillable in Model.
Illuminate\Database\QueryException SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect double value: 'required' for column db_productmanagementsystem.products.price at row 1 (SQL: insert into products (title, type, firstname, surname, price, papl, updated_at, created_at)
Model: Product.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = ['title', 'type', 'firstname', 'surname', 'price', 'papl'];
//use HasFactory;
}
ProductController.php
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$products=product::all();
return view('products', ['products'=>$products]);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return view('createProduct');
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
request()->validate([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required',
'papl' => 'required'
]);
Product::create([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required',
'papl' => 'required'
]);
return redirect('/products');
}
/**
* Display the specified resource.
*
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function show(Product $id)
{
return view('singleProduct', ['product'=>$id]);
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function edit(Product $id)
{
return view('editProduct', ['product'=>$id]);
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function update($id)
{
request()->validate([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required',
'papl' => 'required'
]);
$product=product::findOrFail($id);
$product->title = request('title');
$product->type = request('type');
$product->firstname = request('firstname');
$product->surname = request('surname');
$product->price = request('price');
$product->papl = request('papl');
$product->save();
return redirect('/products');
}
/**
* Remove the specified resource from storage.
*
* #param \App\Models\Product $product
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$product=product::find($id)->delete();
return redirect('/products');
}
}
Database:
enter image description here
You didn't provide the right value to your product model.
Recheck your store method
Product::create([
'title' => 'required',
'type' => 'required',
'firstname' => 'required',
'surname' => 'required',
'price' => 'required', // here you passed a string. but this field type is double in the database schema
'papl' => 'required'
]);
you should get the Product values from the request:
Product::create([
'title' => $request->input( 'title'),
'type' => $request->input('type'),
'firstname' => $request->input('firstname'),
'surname' => $request->input('surname'),
'price' => $request->input('price'),
'papl' => $request->input('papl')
]);
I have multiple resources and mostly resource content few fields that are same for all other resource and it's very difficult to modify all the resource in case I need to update/add key/value in the resource.
Is there any way that I can create one main resource that will contain all common fields and then call the main resource in my another resource and add few additional fields.
Here is my controller where I am calling CitizenFeedResource file.
if ($events->total()) {
return CitizenFeedResource::collection($events);
}
This is my CitizenFeedResource file.
use Illuminate\Http\Resources\Json\JsonResource;
class CitizenFeedResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'start_timestamp' => optional($this->start_timestamp)->toDateTimeString(),
'end_timestamp' => optional($this->end_timestamp)->toDateTimeString(),
'location' => [
'name' => $this->location,
'landmark' => $this->landmark,
'coordinates' => $this->coordinates,
'city' => $this->city,
],
'open_event' => $this->open_event,
'full_day_event' => $this->full_day_event,
'banner' => $this->banner,
'url' => $this->path(),
'web_url' => $this->webUrl(),
'categories' => $this->categories,
'timestamp' => $this->created_at->toDateTimeString(),
'timestamp_ago' => $this->created_at->diffForHumans(),
'statistics' => $this->statistics,
'additional_details' => $this->additionalDetails(),
'municipal_details' => $this->municipal_details,
'user' => optional($this->user)->getProfile($this->channel, '1.1'),
'complaint_id' => $this->complaint_id,
'volunteers' => (isset($this->volunteers) && $this->volunteers) ? $this->user->getVolunteerProfile($this->volunteers, '1.1') : array(),
'share_count' => (isset($this->statistics) && isset($this->statistics['share_count'])) ? array_sum($this->statistics['share_count']) : 0,
'volunteer_status' => $this->getVolunteerStatus($request),
'editable' => $this->editable(),
'type' => 'Event',
];
}
}
You don't have to extend directly from JsonResponse, so you can create one main object let's say like this:
use Illuminate\Http\Resources\Json\JsonResource;
class BaseResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
];
}
}
and then
class CitizenFeedResource extends BaseResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
$data = parent::toArray($request);
$data['custom_field'] = $this->custom_field;
// ...
return $data;
}
}
I am using ajax validation for unique field and it's not working.
In my usercontroller it works but in this sitecontroller doesn't.
Can anyone help me for this?
This is my Controller
<?php
namespace frontend\controllers;
use Yii;
use yii\base\InvalidParamException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\models\LoginForm;
use frontend\models\PasswordResetRequestForm;
use frontend\models\ResetPasswordForm;
use frontend\models\SignupForm;
use frontend\models\User;
use frontend\models\UserSeacrh;
use frontend\models\ContactForm;
use yii\widgets\ActiveForm;
/**
* Site controller
*/
class SiteController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout', 'signup'],
'rules' => [
[
'actions' => ['signup'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['#'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* Displays homepage.
*
* #return mixed
*/
public function actionIndex()
{
return $this->render('index');
}
/**
* Logs in a user.
*
* #return mixed
*/
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
/**
* Displays contact page.
*
* #return mixed
*/
public function actionContact()
{
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.');
} else {
Yii::$app->session->setFlash('error', 'There was an error sending email.');
}
return $this->refresh();
} else {
return $this->render('contact', [
'model' => $model,
]);
}
}
/**
* Displays about page.
*
* #return mixed
*/
public function actionAbout()
{
return $this->render('about');
}
/**
* Signs user up.
*
* #return mixed
*/
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
public function actionValidation()
{
$model = new User();
if(Yii::$app->request->isAjax && $model->load(Yii::$app->request->post()))
{
Yii::$app->response->format = 'json';
return ActiveForm::validate($model);
}
}
/**
* Requests password reset.
*
* #return mixed
*/
public function actionRequestPasswordReset()
{
$model = new PasswordResetRequestForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail()) {
Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
return $this->goHome();
} else {
Yii::$app->session->setFlash('error', 'Sorry, we are unable to reset password for email provided.');
}
}
return $this->render('requestPasswordResetToken', [
'model' => $model,
]);
}
/**
* Resets password.
*
* #param string $token
* #return mixed
* #throws BadRequestHttpException
*/
public function actionResetPassword($token)
{
try {
$model = new ResetPasswordForm($token);
} catch (InvalidParamException $e) {
throw new BadRequestHttpException($e->getMessage());
}
if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
Yii::$app->session->setFlash('success', 'New password was saved.');
return $this->goHome();
}
return $this->render('resetPassword', [
'model' => $model,
]);
}
}
This is my model
<?php
namespace frontend\models;
use Yii;
/**
* This is the model class for table "user".
*
* #property integer $id
* #property string $username
* #property string $name
* #property string $lastname
* #property string $email
* #property integer $phone
* #property string $notes
* #property string $company
* #property string $password_hash
* #property string $auth_key
* #property integer $status
* #property integer $created_at
* #property integer $updated_at
* #property string $country
* #property string $state
* #property string $city
* #property string $language
* #property integer $salary
* #property string $hiredate
* #property string $birthday
* #property string $address
* #property string $dismission
*/
class User extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'user';
}
public function fields()
{
return [
'id','status'
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['username', 'unique'],
[['username', 'name', 'lastname', 'email', 'phone', 'password_hash'], 'required'],
[['phone', 'status', 'created_at', 'updated_at', 'salary'], 'integer'],
[['hiredate', 'birthday', 'dismission'], 'safe'],
[['username', 'name', 'lastname', 'email', 'notes', 'company', 'password_hash', 'auth_key', 'country', 'state', 'city', 'language', 'address'], 'string', 'max' => 100],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => 'Username',
'name' => 'Name',
'lastname' => 'Lastname',
'email' => 'Email',
'phone' => 'Phone',
'notes' => 'Notes',
'company' => 'Company',
'password_hash' => 'Password Hash',
'auth_key' => 'Auth Key',
'status' => 'Status',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'country' => 'Country',
'state' => 'State',
'city' => 'City',
'language' => 'Language',
'salary' => 'Salary',
'hiredate' => 'Hiredate',
'birthday' => 'Birthday',
'address' => 'Address',
'dismission' => 'Dismission',
];
}
}
This is my view
<?php
/* #var $this yii\web\View */
/* #var $form yii\bootstrap\ActiveForm */
/* #var $model \frontend\models\SignupForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\helpers\ArrayHelper;
use frontend\models\Countries;
use frontend\models\States;
use frontend\models\Cities;
use yii\helpers\Url;
$this->title = 'Signup';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-signup">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to signup:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'form-signup', 'enableAjaxValidation' => true, 'validationUrl' => Url::toRoute('site/validation')]); ?>
<?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'name')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'lastname')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'phone')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'company')->textInput(['autofocus' => true]) ?>
<?= $form->field($model, 'password_hash')->passwordInput()->label('Password') ?>
<?= $form->field($model, 'country')->dropDownList(ArrayHelper::map(Countries::find()->all(),'id','name'),
[
'prompt' => 'Страна',
'onchange' => '
$.post( "../states/lists?id='.'"+$(this).val(), function( data ) {
$( "select#signupform-state" ).html( data );
});'
]); ?>
<?= $form->field($model, 'state')->dropDownList([],
[
'prompt' => 'Регион',
'onchange' => '
$.post( "../cities/lists?id='.'"+$(this).val(), function( data ) {
$( "select#signupform-city" ).html( data );
});'
]); ?>
<?= $form->field($model, 'city')->dropDownList([],[ 'prompt' => 'Город' ]); ?>
<?= $form->field($model, 'language')->dropDownList([
'1' => 'Русский',
'2' => 'English',
'3' => 'Turkce',
]); ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
SiteController.php
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
return \yii\bootstrap\ActiveForm::validate($model);
}
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
SignUpForm.php
public function rules()
{
return [
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if (!$this->validate()) {
return null;
}
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
return $user->save() ? $user : null;
}
signup.php
<?php $form = ActiveForm::begin(['id' => 'form-signup', 'enableAjaxValidation' => true]); ?>
I have table comments with column parent_id.
And this is content of CommentsTable.php:
namespace App\Model\Table;
use App\Model\Entity\Comment;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
/**
* Comments Model
*/
class CommentsTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
$this->table('comments');
$this->displayField('id');
$this->primaryKey('id');
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
$this->belongsTo('Posts', [
'foreignKey' => 'post_id',
'joinType' => 'INNER'
]);
$this->belongsTo('ParentComments', [
'className' => 'Comments',
'foreignKey' => 'parent_id'
]);
$this->hasMany('ChildComments', [
'className' => 'Comments',
'foreignKey' => 'parent_id'
]);
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->add('id', 'valid', ['rule' => 'numeric'])
->allowEmpty('id', 'create')
->requirePresence('body', 'create')
->notEmpty('body')
->requirePresence('path', 'create')
->notEmpty('path')
->add('status', 'valid', ['rule' => 'numeric'])
->requirePresence('status', 'create')
->notEmpty('status')
->add('created_at', 'valid', ['rule' => 'datetime'])
->requirePresence('created_at', 'create')
->notEmpty('created_at')
->add('updated_at', 'valid', ['rule' => 'datetime'])
->requirePresence('updated_at', 'create')
->notEmpty('updated_at');
return $validator;
}
/**
* Returns a rules checker object that will be used for validating
* application integrity.
*
* #param \Cake\ORM\RulesChecker $rules The rules object to be modified.
* #return \Cake\ORM\RulesChecker
*/
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['user_id'], 'Users'));
$rules->add($rules->existsIn(['post_id'], 'Posts'));
$rules->add($rules->existsIn(['parent_id'], 'ParentComments'));
return $rules;
}
}
I want to build rule for field parent_id: exist in ParentComments or equal to 0.
Can you help me?
Thank you very much.
Rules are just callable functions or callable classes. The existsIn() function is just an alias for the ExistsIn class. We can use the to our advantage:
...
use Cake\ORM\Rule\ExistsIn;
class CommentsTable extends Table
{
...
public function buildRules(RulesChecker $rules)
{
...
$rules->add(
function ($entity, $options) {
$rule = new ExistsIn(['parent_id'], 'ParentComments');
return $entity->parent_id === 1 || $rule($entity, $options);
},
['errorField' => 'parent_id', 'message' => 'Wrong Parent']
);
return $rules;
}
}