i try to develop application with yii2 framework,i use beforeSave event to handle createdAt and updatedAt with time() function, this method is :
public function beforeSave($insert)
{
if ($insert) {
$this->createdAt = time();
}
$this->updatedAt = time();
return parent::beforeSave($insert);
}
i just wanna move this method to behaviour and attach it to my model, i create the behaviour class and attach the behaviour to model but it does not work abd pass null to database, my behaviour class is :
namespace app\modules\imdb\behaviors;
use yii\base\Behavior;
use yii\db\ActiveRecord;
class saveTimeBehavior extends Behavior
{
public function events()
{
return [
ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
];
}
public function beforeSave($event)
{
if ($event) {
$this->createdAt = time();
}
$this->updatedAt = time();
return parent::beforeSave($event);
}
}
and the attach code in my model is :
public function behaviors()
{
return [
saveTimeBehavior::className(),
];
}
please help me to handle this with correct way, thanks alot :)
You can do this with TimeStampBehavior. If you have declared the columns(created_at, updated_at) as int(11) for being UNIX timestamp.
use yii\behaviors\TimestampBehavior;
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
But as your attribute names are different or you want to use a different way of calculating the timestamp, you may configure the $createdAtAttribute, $updatedAtAttribute and $value properties like the following:
use yii\db\Expression;
use yii\behaviors\TimestampBehavior;
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'createdAt',
'updatedAtAttribute' => 'updatedAt',
'value' => new Expression('NOW()'),
],
];
}
Uou can do that in a simple way , by identify the type of created_at and updated_at as timestamp when you create the table, and it will be automatically filled in the database when you add new record or update existing one.
Example :
'created_at'=> $this->timestamp(),
'updated_at'=> $this->timestamp(),
Note: You can find more information about creating table using the below link : Yii2 Migration
Related
I have created a new controller to save subscription plans for my website. I am trying to create a new record through the model table but am getting the error: Call to a member function keys() on null in vendor/cakephp/cakephp/src/ORM/Table.php, line 2625.
The code I am trying to execute is.
namespace SubscriptionPlans\Model\Table;
use App\Model\Table\AppTable;
use Cake\Chronos\Chronos;
use Cake\Datasource\ConnectionInterface;
use Cake\Datasource\ConnectionManager;
use Cake\Datasource\EntityInterface;
use SubscriptionPlans\Model\Entity\PartnerPlan;
use SubscriptionPlans\Model\Entity\PartnerPlanSubscription;
use SubscriptionPlans\Services\Period;
class PartnerPlanSubscriptionsTable extends AppTable
{
/** #var ConnectionInterface */
public $_connection;
public function __construct($arg)
{
parent::__construct($arg);
$this->_connection = ConnectionManager::get('default');
}
public function initialize(array $config)
{
parent::initialize($config);
$this->addBehavior('Timestamp', [
'events' => [
'Model.beforeSave' => [
'created_at' => 'new',
'updated_at' => 'always',
]
]
]);
}
public function create($partnerId, $subscriptionPlan, $interval = 'year', $intervalCount = 1, $startDate = null): EntityInterface
{
// If the $subscriptionPlan is a PartnerPlan entity, grab the id.
$planId = ($subscriptionPlan instanceof PartnerPlan) ? $subscriptionPlan->id : $subscriptionPlan;
// Create a new date period based on the provided create params
$period = new Period($interval, $intervalCount, $startDate);
/** #var PartnerPlanSubscription $subscription */
$subscription = $this->newEntity([
'partner_id' => $partnerId,
'partner_plan_id' => $planId,
'starts_at' => $period->getStartDate()->toDateTimeString(),
'ends_at' => $period->getEndDate()->toDateTimeString()
]);
return $this->save($subscription);
}
}
I can see the vendor/cakephp/cakephp/src/ORM/Table.php:2625 is expecting some kind of associated option, but I can't find anything in the documentation about this.
This is an old question but this might be of help to others.
I ran into this same issue with PHP 8.0.13 and XDebug. This seems to be related to the XDebug incompatibility with __debugInfo() mentioned in https://github.com/cakephp/chronos/issues/164. I disabled the XDebug extension and the error magically went away.
I use laravel-excel version 3.1 .
my code is :
class UsersExport implements FromView
{
private $users;
public function __construct()
{
$this->users = User::query()->select('name' , 'family' , 'mobile' ,'national_code' , 'email' , 'registered_from')->get();
}
public function view(): View
{
return view('test', [
'users' => $this->users
]);
}
}
In my controller I called vies function:
return (new UsersExport())->view();
here I got a view (html page) not excel spreadsheet. what should I do?
You need to add use Exportable; in your UserExport class, then call return (new UsersExport())->download('something.xls');
P. S. It is not a good idea to write query in UserExport constructor. It would be better to get them before calling it, then pass to your new UserExport()
So, I have a custom Model extension class called RecursiveModel:
use Illuminate\Database\Eloquent\Model;
use ... RecursiveHelper;
class RecursiveModel extends Model {
private $recursiveHelper = null;
public function __construct(){
$this->recursiveHelper = new RecursiveHelper();
parent::__construct();
}
public function save(array $options = []){
parent::save($options);
}
...
// Additional methods available for Recursive Models (self-referenced `parent_id` relationships)
}
And, a Model that extends this RecursiveModel class instead of the base Model class:
use ... RecursiveModel;
use Illuminate\Database\Eloquent\SoftDeletes;
class Line extends RecursiveModel {
use SoftDeletes;
protected $table = "lines";
protected $primaryKey = "id";
public function parent(){
return $this->belongsTo(self::class, "parent_id", "id");
}
public function children(){
return $this->hasMany(self::class, "parent_id", "id");
}
}
All is well and good, and with previously imported records (back when Line extended Model and not RecursiveModel, I was able to use my RecursiveHelper methods/logic without issue. Now, I'm trying to refresh my database, which calls a Seeder:
use Illuminate\Database\Seeder;
use ... Slugger;
use ... Line;
class LinesSeeder extends Seeder {
public function run(){
$parentLine = Line::create([
"name" => "Line Item",
"slug" => $this->slugger->slugify("Line Item"),
"created_at" => date("Y-m-d H:i:s"),
"updated_at" => date("Y-m-d H:i:s"),
]);
$childLine = Line::create([
"name" => "Child Line Item",
"slug" => $this->slugger->slugify("Child Line Item"),
"parent_id" => $parentLine->id,
"created_at" => date("Y-m-d H:i:s"),
"updated_at" => date("Y-m-d H:i:s"),
]);
...
}
}
As previously stated, when Line extended Model and not RecursiveModel, this code worked without issue. But now, I'm running into this error:
SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value (SQL: insert into lines
(updated_at, created_at) values (2018-08-13 15:56:45, 2018-08-13 15:56:45))
The Line::create([...]); doesn't seem to be receiving the parameter passed; is there something I'm missing when extending Model.php? I've tried adding:
public function create(array $options = []){
parent::create($options);
}
To RecursiveModel, but that just throws another error (and I don't think the create() method is a part of Model.php, but rather Builder.php.)
Also, it's not an issue with protected $fillable, nor is it an issue with setting 'strict' => true, on my mysql connection; already tried both of those to no avail.
As suggested, updated __construct method of RecursiveModel to:
public function __construct(array $attributes = []){
$this->recursiveHelper = new RecursiveHelper();
return parent::__construct($attributes);
}
Unfortunately, still getting the same error.
Edit: Line.php had a __construct method that was carried over from when I was applying $this->recursiveHelper model by model; solution was to update signature to match (as noted above) or remove __construct from extending models.
Model constructors need to take in an array of attributes:
public function __construct(array $attributes = [])
I am using model factories in NewsTableSeeder, but I get this error when I entered db:seed.
I want to know why I can't use create() in my seeder.
Here is my News model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class News extends Model
{
protected $table = 'news';
protected $primaryKey = 'id';
public function home_news_lists() {
return $this->select('id', 'news_title', 'news_update')
->orderBy('news_update', 'DESC')
->limit(5)
->get();
}
public function lists() {
return News::all();
}
}
Model Factories:
$factory->define(App\Models\News::class, function (Faker\Generator $faker)
{
static $password;
$faker = $faker->create('zh_TW');
return [
'news_title' => $faker->sentence(),
'news_content' => $faker->paragraph(),
'news_author' => $faker->name(),
'news_pageviews' => $faker->numberBetween(1, 100),
'news_file' => ' ',
'news_img' => $faker->imageUrl($width, $height, 'business'),
'created_at' => $faker->dateTimeBetween('2012', 'now', 'zh_TW'),
'updated_at' => $faker->dateTimeBetween('2015', 'now', 'zh_TW')
];
});
NewsTableSeeder :
<?php
use Illuminate\Database\Seeder;
class NewsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
factory(App\Models\News::class, 50)->create();
}
}
I can't tell 100% without seeing exactly the error you got, but I do believe there is no create() method on the $faker object.
I believe what you mean to do is:
$factory->define(App\Models\News::class, function (Faker\Generator $faker)
{
static $password;
$faker = \Faker\Factory::create('zh_TW'); // change to this
return [
...
];
}
I would just create a new faker generator (\Faker\Generator) that gets returned from calling \Faker\Factory::create($locale) and use that instead. Otherwise, I believe your next best option is to override wherever Laravel instantiates the \Faker\Generator $faker object that gets passed into the callback, but that may get hacky if Laravel doesn't provide a clean way to do it.
The create() method is a static call on the \Faker\Factory method. It accepts a locale as the parameter and uses en_US as the default locale.
$faker = $faker->create('zh_TW');
The error message said this code is wrong.
What is your purpose to use this code?
I am creating offer for products thats why I have implemented several model at create function in controller
public function actionCreate()
{
$model = new Offer();
$wmodel = new Wmoffer();
$pmodel = new Product();
$ummodel = new Unitofmeasurement();
$qvmodel = new OfferingValue();
$blmodel = new OfferLocation();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// code manipulation
}else{
return $this->render('create', [
'model' => $model,
'wmodel' => $wmodel,
'pmodel' => $pmodel,
'qvmodel' => $qvmodel,
'blmodel' => $blmodel,
'ummodel' => $ummodel
]);
}
all of my model extends by ActiveRecord aspect Wmoffer() this model looks like as below
use Yii;
use yii\base\Model;
use yii\web\UploadedFile;
use yii\helpers\FileHelper;
class Wmoffer extends Model
{
public $bIsProductOrService;
public $iCatalogueID;
public $imageProduct;
public $nHasCurrencyValue;
public $nHasCurrencyValueMRP;
public $BusinesslocationIds;
public function rules()
{
// validation rules
Now i need to implement inline validator for start,end date comparison [Start Date should be greater than End Date ]
i have tried this and this but this is not working i know something is missing which causes this
Any suggestions will be appreciable. Thanks
You should check $model->errors value after calling $model->validate() to look for validation errors.
Your dates validator method can be something like:
public function validateDates($attribute, $params) {
if ($this->hasErrors()) {
return;
}
if ($this->dateStart > $this->dateEnd)) {
$this->addError($attribute, 'Start date can not be greater than end date');
}
}
Add it to rules() in your backend models.