yii2 getting data from two models and presenting it in view - yii2

I have two models users and pictures
To draw all pictures in view I have to get string from pictures, one of data is userID, then get string from users according to that userID, so I get userFolder
Then I can draw picture using combined data.
And this must be done for all pictures in DB.
I can start from controller
$picturesModel= Pictures::find()->all();
But then I have to do what? run a loop while which get users data, and then get complete data for drawing a picture and store it in some new array which after loop finish I should pass to view? Is this the best way ? or there is anything simple ?

Assuming that your Pictures has a relation one to one with Users
the you can add to you Pictures model a function
class Pictures extends ActiveRecord
{
// ...
public function getUser()
{
return $this->hasOne(Users::className(), ['id' => 'user_id']);
}
}
then if you controller or in your view you need accessing to the user related to the picture you can
$pictureModel = Pictures::find()->where(['id'=>123])->one();
You can access to the user related
$userModel= $pictureModel->User;
or for a collection of pictures
$picturesModels= Pictures::find()->all();
$userModel = $picturesModels[0]->user
or for the loop
$picturesModels= Pictures::find()->all();
foreach( $picturesModels as $key => $value ) {
echo $value->user->your_att;
}
you can take a look at http://www.yiiframework.com/doc-2.0/guide-db-active-record.html and http://www.yiiframework.com/doc-2.0/guide-db-active-record.html#relational-data

Related

Eloquent query problem using with() function for model relationship eager loading

How do write this eloquent query in Laravel so that it eager loads with() the relationship model in this example between a User model and Profile model? I was trying to avoid 2 separate queries.
I feel I am close, but somethings not quite right.
$author = User::where('id', $id)->with('profile')->get();
The collection is returning the user details correctly. But it's showing the profile relationship as null.
#relations: array:1 [▼
"profile" => null
]
I believe I have things setup correctly with a User model and a Profile needed relationships.
User.php
public function profile()
{
return $this->hasOne('App\AuthorProfile', 'user_id');
}
AuthorProfile.php
public function user()
{
return $this->belongsTo('App\User');
}
Assuming for AuthorProfile model table you have record with id of user it should be fine.
However you wrote:
I was trying to avoid 2 separate queries.
Well, it's not true, if you have single record, eager loading won't help you at all. In this case 2 queries will be execute - no matter if you use eager loading or you won't.
Eager loading would help if you had multiple users and for each of them you wanted to load profile, but if you have single record it won't change anything.
Additionally instead of:
$author = User::where('id', $id)->with('profile')->get();
you should rather use:
$author = User::with('profile')->find($id);
because you expect here single user.
$users = User::with('profile')->find($id);
Your model should be like this.The User_id on the profile table and id on the user table
public function profile()
{
return $this->hasOne('App\AuthorProfile', 'user_id','id');
}

Expanding this method to write to the database

Hi I followed a tutorial to implement a friend system. It all works find, but I need to post other columns to the row that just the id's. How would I expand that.
This is the method that is accessed when the add friend button is clicked
public function getAdd($id){
$user = User::where('id', $id)->first();
//After passing all checks. Add other account
Auth::user()->addFriend($user);
echo "Sent";
}
AddTenancy Method
public function addFriend(User $user){
$this->friendsOf()->attach($user->id);
}
I assume the relationship is many-to-many between users. And you need to add additional data to the pivot.
Here's how you'd do that:
public function addFriend(User $user){
$this->friendsOf()->attach($user->id, ['another_col' => 'some data']);
}
Replace 'another_col' and some data with your column and your data. You can also add more than 1 column into the array.

Foreign keys and uploading a photo in yii 1.1

i did these two tasks separately but now i am not being able to use both of these tasks at a single place.
Problem statement:
I have a table name Business_items having foreign keys of table business and items. In model class here is the relation function.
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'business' => array(self::BELONGS_TO, 'Business', 'business_id'),
'items' => array(self::BELONGS_TO, 'Items', 'items_id'),
'itemReviews' => array(self::HAS_MANY, 'ItemReview', 'business_items_id'),
);
}
ok, in create business page, i have two fields, business name, items name and a third thing which is upload image. Both of the fields are searchable drop downs. I am taking business name and items name with the help of foreign keys. so i can see the values inside my business_items which were used to be keys. i did this by changing this code.
public function actionCreate()
{
$model=new PackageItems;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['PackageItems']))
{
$temp=$model->items_id=$_POST['PackageItems']['items_id']; //items_id is a multiple list field
foreach($temp as $t)
{
$model->unsetAttributes();
$model->setIsNewRecord(true);
$model->package_id=$_POST['PackageItems']['package_id']; //package_id is a repeated field
$model->items_id=$t;
$model->insert();
}
if($model->save())
$this->redirect(array('admin','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
so what i wanted i actually accomplished which was
id----items----package
1------cake-----buy one get one free
2----- pastry-----buy one get one free
second part:
I know how to upload image in yii, i followed this link and it worked http://www.yiiframework.com/wiki/349/how-to-upload-image-photo-and-path-entry-in-database-with-update-functionality/
separately now the problem is i want something like that
id----items----package-----------------------image
1------cake-----buy one get one free------1.jpg
2----- pastry-----buy one get one free------1.jpg
but the problem is
public function actionCreate()
{
$model=new Banner; // this is my model related to table
if(isset($_POST['Banner']))
{
$rnd = rand(0,9999); // generate random number between 0-9999
$model->attributes=$_POST['Banner'];
$uploadedFile=CUploadedFile::getInstance($model,'image');
$fileName = "{$rnd}-{$uploadedFile}"; // random number + file name
$model->image = $fileName;
if($model->save())
{
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName); // image will uplode to rootDirectory/banner/
$this->redirect(array('admin'));
}
}
$this->render('create',array(
'model'=>$model,
));
}
how can i use both of these codes (getting value using foreign key code and picture uploading code) i want to upload pictures as well as get the value from some other table using foreign key with my code.
I know its complicated but i need help.
Thanks and sorry in advance.
I'm not sure if I get your problem right, but as far as I understood, you want to upload a file and insert the name of this file in one of your database tables. If that's the case, a solution could be as follows:
First, add a new field to your database table in which you will store the file name, also add it to your ActiveRecord class and to your view.
Then add your code to save your related records (I think your foreach loop is for that).
Next add a the necessary code to upload the image. In the code to upload the image you can see that Yii will treat the file field like a normal text field, in which you will store the uploaded file name.
Finally you should save your model and, if it succeded, then proceed to save the file in the server.
Hope this helps.
UPDATE
I'll put some code in order to clarify my answer.
You say that the first part works for you, then I'll begin with that.
Your model PackageItems needs a new field, let it be image.
Next, I'm assuming that the user filled the form, so I'll skip the if and the render parts
$temp=$model->items_id=$_POST['PackageItems']['items_id'];
$uploadedFile=CUploadedFile::getInstance($model,'image');//get uploaded image info
$rnd = rand(0,9999);
$fileName = "{$rnd}-{$uploadedFile}"; // random number + file name
$model->image = $fileName;//store the new file name in the model
foreach($temp as $t){
$model->unsetAttributes();
$model->setIsNewRecord(true);
$model->package_id=$_POST['PackageItems']['package_id'];
$model->items_id=$t;
$model->insert();
}
if($model->save()){
$uploadedFile->saveAs(Yii::app()->basePath.'/../yourPath/'.$fileName);//if the record was saved in the database, then proceed to save the image in the server
$this->redirect(array('admin','id'=>$model->id));
}
If you want to upload multiple files check this link Yii 1.1: Uploading multiple images with CMultiFileUpload

Several identical relations to one model in Yii2

I have a model File to store uploaded files and information about these files. Also there is a model with Company relations logo hasOne(File::className()) and photos hasMany(File::className()). Relations are written and works fine. Now I need to make an edit form for model Company in which I could edit files associated in logo and photos. Please tell me how I can do it.
Your relations can reflect the different use-cases, so in your Company model you can have
public function getLogo(){
//You'll need to add in the other attributes that define how Yii is to retrieve the logo from your images
return $this->hasOne(File::className(), ['companyId' => 'id', 'isLogo' => true]);
}
public function getPhotos(){
//You'll need to add in the other attributes that define how Yii is to retrieve the photos from your images
return $this->hasMany(File::className(), ['companyId' => 'id', 'isLogo' => false]);
}
You can then just use them like normal attributes;
$company = new Company;
$logo = $company->logo;
$photos = $company->photos;
You will then need to set up your controller to handle changes in these values to deal with uploads or new images, but that will depend on how you are handling the uploads.

Codeigniter Noob Question--active record and results?

I'm writing a simple app. I need to block user from a page if their credit is < 0.
I have a table "User_profiles" with a "credit" row.
How can I set up a model in conjunction with the controller to send the user to another page if the value of "credit" is 0?
This should be straightforward, but I'm new at the select->where stuff...
It has to be the row of the current user too--I don't know how to traverse arrays very well yet.
Thanks!
Well, the easiest solution would be to just load a different view...
As for the model, it would look like this:
class UserModel extends Model {
public function getUserCredit($id) {
$this->load->database();
//effectively generates: SELECT `credit` FROM `User_profiles` WHERE `id`=$id
$query = this->db->select('credit')->where('id',$id)->get('User_profiles');
//row() executes the query for a single result, returns the credit property
return $query->row()->credit;
}
}
Then in the controller:
class Users extends Controller {
//....
public function credit() {
$this->load->model('userModel','users');
// assuming the session library has been loaded
$user_id = $this->session->userdata('id');
$credit = $this->users->getUserCredit($user_id);
if ($credit == '0') $this->load->view('users/no_credit');
else $this->load->view('users/credit');
}
}
That's untested, but it should at least help you get the idea.
When you request the page /users/credit/1, CI will call the Users::credit(1) action.
It then loads UserModel as $this->users
You call $this->users->getUserCredit(1), which translates to UserModel::getUserCredit(1), to store as $credit
The model loads the database.
You tell the db to select('credit') (select the credit column), where('id',1) (where the id = 1), then get('User_profiles') (get matching rows from the User_profiles table). That returns a query, which you store as $query for readability.
getUserCredit returns the credit property of the single-row result of the query
If $credit == 0, you load the view views/users/no_credit.php
Otherwise, you load the view views/users/credit.php (it's conventional to name the views after the actions they represent and put them in a folder corresponding to the controller)