Upload the file to a folder and saving the name to the database in yii2 - yii2

Good afternoon!
There is a question about the file upload to yii2. There are two folders in it that will store the original and thumbnail image. At me files are loaded but here the name of a file does not load in a database
Model
namespace app\models;
use yii\base\Model;
use yii\db\ActiveRecord;
use yii\web\UploadedFile;
use yii\imagine\Image;
use Imagine\Image\Box;
/**
* This is the model class for table "images".
*
* #property integer $id
* #property string $original_image
* #property string $prev_image
*/
class Images extends ActiveRecord
{
public $imageFile;
public $file_name;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'images';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['prev_image'], 'string', 'max' => 255],
[['original_image'], 'string'],
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg', 'maxSize' => 1024 * 1024 * 7],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'original_image' => 'Original Image',
'prev_image' => 'Prev Image',
];
}
public function upload()
{
$temp=substr(md5(microtime() . rand(0, 9999)), 0, 20);
if ($this->validate()) {
$this->imageFile->saveAs('uploads/original/'.$temp.$this->imageFile->baseName . '.' . $this->imageFile->extension);
$imagine = Image::getImagine();
$image = $imagine->open('uploads/original/' . $temp.$this->imageFile);
$image->resize(new Box(250, 150))->save('uploads/prev/' . $temp.$this
->imageFile->baseName . '.' . $this->imageFile->extension, ['quality' => 70]);
$this->file_name=$temp.$this->imageFile->baseName . '.' . $this->imageFile->extension;
return true;
} else {
return false;
}
}
}
Controller
namespace app\controllers;
use app\models\Images;
use Yii;
use yii\web\UploadedFile;
class ImageController extends \yii\web\Controller
{
public function actionUpload()
{
$model = new Images();
if ($model->load(Yii::$app->request->post())) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
$model->prev_image=$model->file_name;
$model->original_image=$model->file_name;
$model->save();
if ($model->upload()) {
return;
}
}
return $this->render('upload', ['model' => $model]);
}
}
A question how to save a file name in database? Thank you in advance

It's because save happens before uplaod action, but you only define file_name in upload function. Save is what saves it in to the database.
Controller should look like this:
namespace app\controllers;
use app\models\Images;
use Yii;
use yii\web\UploadedFile;
class ImageController extends \yii\web\Controller
{
public function actionUpload(){
$model = new Images();
if ($model->load(Yii::$app->request->post())) {
$uploadedFile = UploadedFile::getInstance($model, 'imageFile');
$model->imageFile = $uploadedFile;
$model->prev_image = $uploadedFile->name
$model->original_image = $uploadedFile->name
$model->save();
if ($model->upload()) {
return;
}
}
return $this->render('upload', ['model' => $model]);
}
}

Related

Yii2 Multilingual. Can't reach the fields from the translation table

I installed OmgDef/Multilingual via composer. Did everything step by step from the guide. The error that I get now is:
Getting unknown property: backend\models\PageAdminSearch::title
I added joinWith('translation') but nothing changes.This is my PageAdmin model and PageAdminSearch
PageAdmin:
<?php
namespace backend\models;
use omgdef\multilingual\MultilingualBehavior;
use omgdef\multilingual\MultilingualQuery;
use Yii;
/**
* This is the model class for table "page_admin".
*
* #property int $id
* #property int $id_in
* #property int $enable
* #property string $icon
*/
class PageAdmin extends \yii\db\ActiveRecord
{
public static function find()
{
return new MultilingualQuery(get_called_class());
}
public function behaviors()
{
$allLanguages = [];
foreach (Yii::$app->params['languages'] as $title => $language) {
$allLanguages[$title] = $language;
}
return [
'ml' => [
'class' => MultilingualBehavior::className(),
'languages' => $allLanguages,
//'languageField' => 'language',
//'localizedPrefix' => '',
//'requireTranslations' => false',
//'dynamicLangClass' => true',
//'langClassName' => PostLang::className(), // or namespace/for/a/class/PostLang
'defaultLanguage' => Yii::$app->params['languageDefault'],
'langForeignKey' => 'page_id',
'tableName' => "{{%page_adminlang}}",
'attributes' => [
'title',
'content',
]
],
];
}
/**
* #inheritdoc
*/
public static function tableName()
{
return 'page_admin';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['icon'], 'string'],
[['id_in', 'enable'], 'integer']
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'id_in' => Yii::t('app', 'Id In'),
'icon' => Yii::t('app', 'Icon'),
];
}
}
PageAdminSearch:
<?php
namespace backend\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use backend\models\PageAdmin;
/**
* PageAdminSearch represents the model behind the search form of `backend\models\PageAdmin`.
*/
class PageAdminSearch extends PageAdmin
{
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'id_in'], 'integer'],
];
}
/**
* #inheritdoc
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = PageAdmin::find()->joinWith('translations');
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'id_in' => $this->id_in,
]);
$query->andFilterWhere(['like', 'title', $this->title]);
return $dataProvider;
}
}
languageDefault is bg. Did someone have the same problem? The explanation is not pretty big but I think the problem is clear enough :) Appreciate every advice!
Haven't used it tho but looking at your code you are adding a joinWith inside the search() function in the model, are you searching any field with name title inside the translations table using some gridview or search form
If that is so you need to declare a custom attribute inside your searchModel and add it to the safe rules and then use it because you are getting an error at the line
$query->andFilterWhere(['like', 'title', $this->title]);
so add a custom attribute on top of your PageAdminSearch
public $title
And it is always good to use an alias for the relation
$query = PageAdmin::find()
->joinWith(['translations'=>function($q){
$q->from('{{%transalations}} tr');
}]);
then update your rules to the following
/**
* #inheritdoc
*/
public function rules()
{
return [
[['id', 'id_in'], 'integer'],
[['title'],'safe'],
];
}
and change the line to the following
$query->andFilterWhere(['like', 'tr.title', $this->title]);
Now run it won't show you the error.

Argument 1 passed to yii\web\User::login() must implement interface yii\web\IdentityInterface

These are my files:
config/web.php
'user' => [
'identityClass' => '\app\models\User',
'enableAutoLogin' => false,
],
SiteController.php
public function actionSignin()
{
$model = new SigninForm();
if(!Yii::$app->user->isGuest)
{
return $this->goHome();
}
if($model->load(Yii::$app->request->post()) and $model->validate())
{
$identity = User::findOne(['email' => $model->email])
Yii::$app->user->login($identity);
}
return $this->render('signin',compact('model'));
}
User.php
namespace app\models;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
/* and all methods Identityinterface is here!*/
}
I'm getting an error that I'm not using IdentityInterface in my User.php model. Where is my mistake?
You need to define all the methods necessary for Implementing IdentityInterface
as given here, and 2 additional methods that would be used by the login method add them to your class first.
class User extends ActiveRecord implements IdentityInterface
{
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null)
{
return static::findOne(['access_token' => $token]);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authKey;
}
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* Validates password
*
* #param string $password password to validate
* #return bool if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
Then you SigninForm should look like following
<?php
namespace app\models;
use Yii;
use yii\base\Model;
/**
* SigninForm is the model behind the login form.
*
* #property User|null $user This property is read-only.
*
*/
class SigninForm extends Model {
public $username;
public $password;
public $rememberMe = true;
private $_user = false;
/**
* #return array the validation rules.
*/
public function rules() {
return [
// username and password are both required
[['username', 'password'], 'required'],
// rememberMe must be a boolean value
['rememberMe', 'boolean'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* #param string $attribute the attribute currently being validated
* #param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params) {
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
* #return bool whether the user is logged in successfully
*/
public function login() {
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0));
}
return false;
}
/**
* Finds user by [[username]]
*
* #return User|null
*/
public function getUser() {
if ($this->_user === false) {
$this->_user = User::findOne($this->username);
}
return $this->_user;
}
}
Update your Signup action to the following
public function actionSignin()
{
$model = new SigninForm();
if(!Yii::$app->user->isGuest)
{
return $this->goHome();
}
if($model->load(Yii::$app->request->post()) && $model->login())
{
return $this->goBack();
}
return $this->render('signin',compact('model'));
}
And then add the following inside your config/web.php under components as it is shown in the following example:
'components'=>[
'user' => [
'identityClass' => 'app\models\User', // User must implement the IdentityInterface
'enableAutoLogin' => true,
// 'loginUrl' => ['user/login'],
// ...
]
]
You should look into documentation more thoroughly here is a good video tutorial that would guide you step by step to implement your login interface.
Hope it helps

Move file from one directory to other directory in yii2

I have uploaded file on my shared server now I want to move file using yii2 libraries how can I move this file.
Simple use this:
http://php.net/manual/en/function.rename.php
or in uploadAction you can use saveAs method when you upload file like this:
public function actionUpload()
{
$model = new UploadForm();
if (Yii::$app->request->isPost) {
$model->imageFile = UploadedFile::getInstance($model, 'imageFile');
if ($model->upload()) {
// file is uploaded successfully
return;
}
}
return $this->render('upload', ['model' => $model]);
}
class UploadForm extends Model
{
/**
* #var UploadedFile
*/
public $imageFile;
public function rules()
{
return [
[['imageFile'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg'],
];
}
public function upload()
{
if ($this->validate()) {
$this->imageFile->saveAs('uploads/' . $this->imageFile->baseName . '.' . $this->imageFile->extension);
return true;
} else {
return false;
}
}
}
manual:
http://www.yiiframework.com/doc-2.0/guide-input-file-upload.html

Yii::$app->user->isGuest always true on main.php after login

I want to implement user login into yii2 basic app.everything works properly except, when I tries to access Yii::$app->user->isGuest on layout main page. it always returns true. whats going wrong here?, please help me
public function actionLogin()
{
if (!Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
Yii::$app->user->isGuest; // i m getting this as false, which is correct, but after goBack(), I m getting it as true
return $this->goBack();
}
return $this->render('login', [
'model' => $model,
]);
}
Login Mehod from LoginForm.php
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
}
return false;
}
Note : I am using custom theme, which rests outside the web folder and inside project/themes/ directory
** User Model is as follows**
<?php
namespace app\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
use yii\web\NotFoundHttpException;
class User extends ActiveRecord implements IdentityInterface {
private $id;
private $authKey;
const STATUS_DELETED = '0';
const STATUS_ACTIVE = '10';
public static function tableName() {
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function behaviors() {
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function getId() {
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey() {
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password) {
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
public static function findByEmail($email) {
$user_type = ['U'];
return static::find()
->andWhere('email = :email', [':email' => $email])
->andFilterWhere(['in', 'user_type', $user_type])
->one();
}
public static function findIdentity($id) {
$user = static::find()->where(['id' => $id, 'status' => self::STATUS_ACTIVE,])->one();
if (empty($user->id)) {
\Yii::$app->session->destroy();
}
return $user;
}
public static function findIdentityByAccessToken($token, $type = null) {
$user = static::find()
->where([
'access_token' => $token,
'status' => self::STATUS_ACTIVE,
])
->one();
if (!empty($user)) {
return $user;
} else {
throw new NotFoundHttpException('Invalid access token.');
}
}
}
Remove the lines:
private $id;
private $authKey;
from User class.
You should not directly declare ActiveRecord attributes that come from database as stated in the Guide.
Note: The Active Record attributes are named after the associated table columns in a case-sensitive manner. Yii automatically defines an attribute in Active Record for every column of the associated table. You should NOT redeclare any of the attributes.

yii2 adding '0=1' to query on many to many relation

I have a project where users must be connected with each others - like friends. So i decided to connect them by the table 'connect'. Looks like it's rights. But when i tried to search for a friend requests i got the error, described below.
Here is my model User:
<?php namespace common\models
use dektrium\user\models\User as BaseUser;
use Yii;
use yii\data\ActiveDataProvider;
use yii\helpers\ArrayHelper;
use dosamigos\taggable\Taggable;
use yii\db\ActiveQuery;
/**
* User model
*
* #inheritdoc
* #property string $search
* #property string $category
*
* #property ActiveQuery $requests
*/
class User extends BaseUser
{
#region Properties
public $category;
public $search;
const SCENARIO_CATEGORY = 'category';
const SCENARIO_SEARCH = 'search';
#endregion
#region Yii
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function rules()
{
return array_merge(parent::rules(), [
[['category'], 'safe', 'on' => self::SCENARIO_CATEGORY],
[['search'], 'safe', 'on' => self::SCENARIO_SEARCH],
]);
}
/**
* #inheritdoc
*/
function scenarios()
{
return array_merge(parent::scenarios(), [
self::SCENARIO_CATEGORY => ['category'],
self::SCENARIO_SEARCH => ['search']
]);
}
#endregion
#region Callbacks
function afterFind()
{
$this->category = implode(', ', ArrayHelper::map($this->getCategories()->asArray()->all(), 'id', 'name'));
parent::afterFind();
}
/**
* #inheritdoc
*/
public function behaviors()
{
return array_merge(parent::behaviors(), [
[
'class' => Taggable::className(),
'attribute' => 'category',
'relation' => 'categories',
]
]);
}
#endregion
#region Relations
/**
* #return \yii\db\ActiveQuery
*/
function getCategories()
{
return $this->hasMany(Category::className(), ['id' => 'category_id'])->viaTable('{{%category_user}}', ['user_id' => 'id']);
}
/**
* #return \yii\db\ActiveQuery
*/
function getRequests()
{
return $this->hasMany(User::className(), ['id' => 'user_two'])->viaTable(Connection::tableName(), ['user_one' => 'id']);
}
#endregion
#region Methods
function search($params)
{
$query = self::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
// if (!$this->validate()) {
// $query->where('0=1');
// return $dataProvider;
// }
$query->joinWith(['categories']);
$query->andFilterWhere(['like', 'category.name', $this->search]);
return $dataProvider;
}
function isConnected($user_id)
{
return Connection::isConnected(Yii::$app->user->id, $user_id);
}
function requestCount()
{
return Connection::requestCount(Yii::$app->user->id);
}
function requestPends()
{
$query = $this->getRequests();
$result = new ActiveDataProvider([
'query' => $query
]);
$query->joinWith(['requests']);
$query->from(User::tableName() . ' u1');
$query->where = "";
$query->andFilterWhere(['connection.status' => Connection::STATUS_PENDED]);
return $result;
}
#endregion
}
Here is my connection model:
namespace common\models;
use Yii;
use yii\data\ActiveDataProvider;
use yii\db\Query;
/**
* This is the model class for table "connection".
*
* #property integer $id
* #property integer $user_one
* #property integer $user_two
* #property integer $status
*
* #property User $userOne
* #property User $userTwo
*/
class Connection extends \yii\db\ActiveRecord
{
const STATUS_PENDED = 0;
const STATUS_ACCEPTED = 1;
const STATUS_DENIED = 2;
public static function primaryKey()
{
return array('id');
}
/**
* #inheritdoc
*/
public static function tableName()
{
return 'connection';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['user_one', 'user_two', 'status'], 'integer'],
[['user_one'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_one' => 'id']],
[['user_two'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_two' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'user_one' => Yii::t('app', 'User One'),
'user_two' => Yii::t('app', 'User Two'),
'status' => Yii::t('app', 'Status'),
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getUserOne()
{
return $this->hasOne(User::className(), ['id' => 'user_one']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getUserTwo()
{
return $this->hasOne(User::className(), ['id' => 'user_two']);
}
function search($params)
{
$query = self::find();
$result = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
// if (!$this->validate()) {
// $query->where('0=1');
// return $result;
// }
return $result;
}
static function isConnected($user_one, $user_two)
{
return self::find()->where('(user_one=:one AND user_two=:two) OR ((user_one=:two AND user_two=:one))', [':one' => $user_one, ':two' => $user_two])->andFilterWhere(['status' => Connection::STATUS_ACCEPTED])->count();
}
static function requestCount($user_id)
{
return (int)self::find()->where(['user_two' => $user_id])->andFilterWhere(['status' => Connection::STATUS_PENDED])->count();
}
}
request view:
<div class="panel panel-default">
<div class="panel-body">
<?php
// if ($mdlUser->requestCount()) {
echo ListView::widget([
'dataProvider' => $mdlUser->requestPends(),
'itemView' => '_list',
]);
// }
?>
</div>
</div>
Controller:
function actionFriendRequest()
{
/** #var User $mdlUser */
$mdlUser = Helper::findModel('\common\models\User', Yii::$app->user->id);
return $this->render('request', [
'mdlUser' => $mdlUser
]);
}
But yii2 make query like
`SELECT `u1`.* FROM `user` `u1` LEFT JOIN `connection` ON `u1`.`id` = `connection`.`user_one` LEFT JOIN `user` ON `connection`.`user_two` = `user`.`id` WHERE ((`connection`.`status`=0)) AND (0=1) LIMIT 20`
Question: Where did the (0=1) came from???
Take a look at your expression:
$mdlUser = Helper::findModel('\common\models\User', Yii::$app->user->id);
Most likely your 0=1 comes from Helper class, findModel method, which you haven't shown here.
UPDATE:
There are two more places where 0=1 can come from: QueryBuilder.php line 1077 and line 1226, which is the way yii2 handles empty strings/arrays for LIKE and IN conditions.