Yii Gridview show image from related data - yii2

i have table feedback and user, i am trying to show user's image on feedback page.
i am using grid view, this is my gridview.
[ 'attribute' => 'iduser.photo',
'headerOptions' => ['width' => '20px'],
'format' => 'image',
'value'=> function($data) { return $data->imageurl; },
],
and the model
public function getImageurl()
{
return \Yii::$app->request->BaseUrl.'/../../'.$this->hasOne(User::className(), ['photo' => 'photo']);
}
i get right url but the photoname is wrong the result is "photo", i want getting the data form entity photo?

Inside your model you should have a way to get the User related to your feedback like this:
public function getUser() {
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
Then your getImageurl method should look something like this:
public function getImageurl()
{
return \Yii::$app->request->BaseUrl.'/../../'.$this->user->photo;
}
I would recommend checking out Aliases, you can use them instead of \Yii::$app->request->BaseUrl. For example, this is the implementation i use to get a file url to show to the user:
public function getFileUrl() {
return Yii::getAlias('#web/uploads/'.$this->fileName);
}

Related

HasONE YII2 link with 2 attributes

``` public function getContaCorrente()
{
return $this->hasOne(\app\models\ContaCorrente::className(), ['id' => 'conta_corrente_id']);
}```
Is it possible to add two attributes in the same get? For example, I have this get above and I want to join it with the get below, as they both look for the same table but different variables.
public function getContaCorrenteAdesao()
{
return $this->hasOne(\app\models\ContaCorrente::className(), ['id' => 'conta_corrente_adesao']);
}
Since this is a query builder you can do something like that:
public function getContaCorrenteAdesao()
{
return $this->hasOne(\app\models\ContaCorrente::className(), ['id' => 'conta_corrente_adesao'])->orWhere(['id' => 'conta_corrente_id']);
}

Yii2: Filter query by pivot table when using `joinWith()`

Take the following sample Cart model. It has a CartItem "pivot record/table" which links it to Item.
class Cart extends ActiveRecord {
public function getCartItems() {
return $this
->hasMany(CartItem::class, ['cart_id' => 'id'])
->inverseOf('cart');
}
public function getItems($callback = null) {
return $this
->hasMany(Item::class, ['item_id' => 'id'])
->via('cartItems', $callback);
}
}
(Example #1) At this point I would be able to filter either by Item's activequery or CartItem's query like so:
$booksAddedToCartSinceYesterday = $cart
->getItems(function($cartItemQuery) {
$cartItemQuery->andWhere('cartItem.created_at > NOW()');
})
->andWhere(['item.category' => 'books']);
(Example #2) But how do I accomplish the same when I use the static find() method in combination with joinWith()? In the following example I am only able to filet by Item's ActiveQuery, but I no longer have any reference to the CartItem's ActiveQuery object:
$booksAddedToCartSinceYesterday = Cart::find()
->andWhere(['cart.user_id' => $some_user_id])
->joinWith([
'items' => function($itemQuery) {
$itemQuery->andWhere(['item.category' => 'books']);
},
]);
How do I modify the code above so that I am able to filter CartItem junction table records like I did in my example #1? How do I access the junction ActiveQuery object so that I can call $cartItemQuery->andWhere('cartItem.created_at > NOW()');?
you can pass any variable value in anonymous function with use keyword link below
make your magic code here for filter or any
->joinWith([
'items' => function($itemQuery) use ($var1,$var2){
$itemQuery->andWhere(['item.category' => 'books']);
$itemQuery->andWhere(['some_condition' => $var1]); <<<---------
},
]);

Having problems in the store method Laravel-Eloquent

Been at this for a very long time and I can't get it right. Would be really thankful for some help. Thanks in advance!
Im trying to build a little clone of reddit some learning purpose.
I think these models is correct for what I'm trying to do. Im able to save a Subreddit to DB with user_id. But my problem is that I can't post to the post table since it's telling me it cannot find the subreddits_id column. Im seems like the method im trying to call should be working but it doesnt.
protected $fillable = ['title', 'link','content', 'post_picture', 'user_id', 'subreddit_id'];
//Functions
public function user () {
return $this->belongsTo(User::class);
}
public function subreddit() {
return $this->belongsTo(Subreddit::class);
}
public function comments () {
return $this->hasMany(Comment::class);
}
Above is my Post model
protected $guarded = [];
//Functions
public function user () {
return $this->belongsTo(User::class);
}
public function posts () {
return $this->hasMany(Post::class);
}
public function comments () {
return $this->hasMany(Comment::class);
}
Above is my Subreddit Model
public function posts () {
return $this->hasMany(Post::class);
}
public function subreddit() {
return $this->hasMany(Subreddit::class);
}
public function commments () {
return $this->hasMany(Comment::class);
}
Above is my User model
I think these models is correct for what I'm trying to do. Im able to save a Subreddit to DB with user_id. But my problem is that I can't post to the post table since it's telling me it cannot find the subreddits_id column. Im seems like the method im trying to call should be working but it doesnt.
The Store method looks like this:
public function store(Request $request)
{ $data = request()->validate([
'title' => 'required',
'link' => 'required',
'content' => 'required',
]);
$post = auth()->user()->posts()->create($data);
return redirect('/home');
}
I'm getting this error General error: 1364 Field 'subreddit_id' doesn't have a default value (SQL: insert into posts (title, link, content, user_id, updated_at, created_at) values (awe, ew, we, 2, 2020-04-01 17:41:29, 2020-04-01 17:41:29))
your $data only takes the parameters you specify for validation, But you did not include subreddit_id, It should be like this:
public function store(Request $request)
{ $data = request()->validate([
'title' => 'required',
'link' => 'required',
'content' => 'required',
'subreddit_id' => 'required|exist:subreddits,id'
]);
$post = auth()->user()->posts()->create($data);
return redirect('/home');
}

Cannot generate HalResource for object of type ArrayObject

I've some problems to return a paginator object as HAL json collection. I'm using the latest versions of zend-expressive and zend-expressive-hal.
This is the setting from my ConfigProvider:
public function __invoke() : array
{
return [
'dependencies' => $this->getDependencies(),
MetadataMap::class => $this->getHalConfig(),
];
}
public function getHalConfig() : array
{
return [
[
'__class__' => RouteBasedCollectionMetadata::class,
'collection_class' => RoleCollection::class,
'collection_relation' => 'user_roles',
'route' => 'api.user.roles',
],
];
}
And these are my handler methods:
public function get(ServerRequestInterface $request) : ResponseInterface
{
// read some records from the database
$select = new Select();
$select->from(['r' => 'user_roles']);
$select->columns(['id', 'name']);
$paginator = new RoleCollection(new DbSelect($select, $this->dbAdapter));
$paginator->setItemCountPerPage(25);
$paginator->setCurrentPageNumber(1);
return $this->createResponse($request, $paginator);
}
private function createResponse(ServerRequestInterface $request, $instance) : ResponseInterface
{
return $this->responseFactory->createResponse(
$request,
$this->resourceGenerator->fromObject($instance, $request)
);
}
The RoleCollection class is only an inheritance of the Paginator:
class RoleCollection extends Paginator
{
}
The error message which I get is:
Cannot generate Zend\Expressive\Hal\HalResource for object of type ArrayObject; not in metadata map
I think you are missing the metadata for the Role object itself.
For example this is something similar for my posts object:
MetadataMap::class => [
[
'__class__' => RouteBasedCollectionMetadata::class,
'collection_class' => Posts::class,
'collection_relation' => 'posts',
'route' => 'api.posts',
],
[
'__class__' => RouteBasedResourceMetadata::class,
'resource_class' => Post::class,
'route' => 'api.posts.view',
'extractor' => ArraySerializable::class,
],
],
You have only described the collection and the resource class is missing for a single role.
I also see the resource generator tries to parse an ArrayObject. This should be wrapped in a Role object, which you can add to the MetadataMap.
Where it goes wrong in your code is this line:
$paginator = new RoleCollection(new DbSelect($select, $this->dbAdapter));
This adds the result of a query into the paginator, but the paginator does not know how to handle it. If I remember correctly, the DbSelect return a ResultSet. I'm guessing this is where the ArrayObject is coming from. What you probably need is to override that ResultSet and make sure it returns an array of Role objects. You might want to look into the dbselect adapter and the hydrating resultset.
Once you have the Role object in the paginator, you can describe it in the metadata.
[
'__class__' => RouteBasedResourceMetadata::class,
'resource_class' => UserRole::class,
'route' => 'api.roles',
'extractor' => ...,
],
I use doctrine myself with hal so zend-db is out of my scope. If you need more help, I suggest the zf forums.

Add new attribute dynamically to the existing model object in Yii2 framework

In Yii2 framework is it possible to add a new attribute dynamically to an existing object, which is retrieved from Database?
Example
//Retrieve from $result
$result = Result::findone(1);
//Add dynamic attribute to the object say 'result'
$result->attributes = array('attempt' => 1);
If it is not possible, please suggest an alternate best method to implement it.
Finally I would be converting the result to a json object. In my application, at the behaviour code block, I have used like this:
'formats' => [
'application/json' => Response::FORMAT_JSON,
],
You can add define a public variable inside your model, that will store dynamic attributes as associative array. It'll look something like this:
class Result extends \yii\db\ActiveRecord implements Arrayable
{
public $dynamic;
// Implementation of Arrayable fields() method, for JSON
public function fields()
{
return [
'id' => 'id',
'created_at' => 'created_at',
// other attributes...
'dynamic' => 'dynamic',
];
}
...
..in your action pass some dynamic values to your model, and return everything as JSON:
public function actionJson()
{
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$model = Result::findOne(1);
$model->dynamic = [
'field1' => 'value1',
'field2' => 2,
'field3' => 3.33,
];
return $model;
}
In result you will get JSON like this:
{"id":1,"created_at":1499497557,"dynamic":{"field1":"value1","field2":2,"field3":3.33}}