I have a ImageController like this:
$image = Image::where('id', $id)->first();
return [
'image' => $image,
'image_360' => $image['360']
];
The previous lines return to the browser the following:
{
"image": {
"id": 1,
"name": "default.jpg",
"360": 1,
},
"image_360": null
}
The Image migration:
$table->increments('id');
$table->string('name');
$table->boolean('360');
The Image model:
class Image extends Model
{
protected $fillable = ['name', '360'];
protected $casts = [
'360' => 'boolean'
];
}
Why $images['360'] returns null if its value is true?
Here is the workaround way: I've tryed many ways but havenot get a direct way to access the number value as descripted in this post
return [
'image' => $image,
'image_360' => array_values($image->toArray())[2];
];
Related
I've got a Product and a Category models:
class Product extends BaseModel
{
use Uuid;
protected $fillable = [
'barcode',
'name',
'sku',
'description',
'type',
'category_id',
'wholesale_price',
'retail_price',
'base_picture',
'current_stock_level',
'active',
];
public function category(): BelongsTo
{
return $this->belongsTo(Category::class, 'category_id');
}
class Category extends BaseModel
{
protected $fillable = [
'name',
'parent',
'description',
'image',
];
public function product(): HasMany
{
return $this->hasMany(Product::class, 'category_id');
}
In my controller, I'm retrieveing all products and wanted to return the category object the product belongs to in the response, so I'm doing:
class ProductsController extends Controller
{
public function index(): AnonymousResourceCollection
{
$products = Product::all();
return ProductsResource::collection($products->loadMissing('category'));
}
and my resource looks like:
class ProductsResource extends JsonResource
{
public function toArray($request) : array
{
return [
'id' => $this->id,
'type' => 'products',
'attributes' => [
'barcode' => $this->barcode,
'name' => $this->name,
'slug' => $this->slug,
'sku' => $this->sku,
'description' => $this->description,
'type' => $this->type,
// todo return category object?
'category' => new CategoriesResource($this->whenLoaded('category_id')),
'wholesale_price' => $this->wholesale_price,
'retail_price' => $this->retail_price,
'base_picture' => $this->base_picture,
'current_stock_level' => $this->current_stock_level,
'active' => $this->active,
]
];
}
}
but the response I'm getting is:
{
"data": [
{
"id": "a2102c4c-c14a-4d16-af28-e218bcc4fe39",
"type": "products",
"attributes": {
"barcode": "1010101010101",
"name": "phione",
"slug": "phione",
"sku": "w2e2r2",
"description": null,
"type": "services",
"wholesale_price": 54,
"retail_price": 34,
"base_picture": null,
"current_stock_level": 0,
"active": 1
}
}
]
}
I tried loading the relationship differently:
public function index(): AnonymousResourceCollection
{
$products = Product::with('category')->get();
return ProductsResource::collection($products);
}
but the result is the same.
It seems that the relationship is well established because if I run:
$product = Product::first();
dd($product->category);
I can see the category the product belongs to:
#attributes: array:8 [▼
"id" => 2
"name" => "Paper"
"slug" => "paper"
"parent" => 1
"description" => null
"image" => null
"created_at" => "2022-09-20 02:03:05"
"updated_at" => "2022-09-20 02:03:05"
]
what am I missing?
In controller load category relation with eager loading
$products = Product::with('category');
return ProductsResource::collection($products);
and in the ProductsResource file load, the relation category, not category_id
'category' => CategoriesResource::collection($this->whenLoaded('category')),
You don't need to use a collection here. Simply do
$products = Product::with('category')->get();
return response()->json($products);
Description and welcomeEmailContents are type text in db ,and both store same type data .
Description return json obj while issue is welcomeEmailContents return string.
$course_desc_blocks = ($courseData['description'] != null) ? json_encode($courseData['description']) : null;
$course_welcome_blocks = ($courseData['welcomeEmailContents'] != null) ? json_encode($courseData['welcomeEmailContents']) : null;
//Laravel Query:-
$courseData = Course::select('id', 'title', 'description','welcomeEmailContents', 'price', 'site_id', 'status', 'expiry_days')->orderBy('id', 'asc'));
return response()->json( $courseData );
//=====================================
//output
{
"data": {
"id": 100,
"title": "Python",
"description": [
{
"type": "paragraph",
"data": {
"text": "jsonTesting"
}
}
],
"welcomeEmailContents": "[{\"type\":\"paragraph\",\"data\":{\"text\":\"Testingjson\"}}]",
"price": 0
}
}
The easiest way to accomplish this would be to add a json cast to the welcomeEmailContents field.
class Course extends Model
{
protected $casts = [
'welcomeEmailContents' => 'json',
];
}
Please note that with the snippet above you no longer have to manually encode the json when setting the field but instead just set it as an array.
Course::create([
// Some more fields...
'welcomeEmailContents' => [
[
'type' => 'paragraph',
'data' => [
'text' => 'testingjson',
],
],
],
]);
There are multiple ways to accomplish the above. You can find more info on this in the documentation: https://laravel.com/docs/8.x/eloquent-mutators
I am creating a custom Identity interface without created_at property. I got an error :
"name": "Unknown Property",
"message": "Setting unknown property: api\\common\\models\\User::created_at",
I tried to comment the TimestampBehavior, but I got the following error:
"name": "PHP Warning",
"message": "Invalid argument supplied for foreach()",
I want to know where is the problem.
Model class:
class User extends ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return '{{%user}}';
}
public function behaviors()
{
// return [
// TimestampBehavior::className(),
// ];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['purpose'], 'required'],
[['status'], 'integer'],
];
}
}
for the rest controller the action is
public function actionLogin(){
.
.
.
$api_user = new User();
$api_user->purpose="app";
$api_user->status=User::STATUS_ACTIVE;
if($api_user->save()){
$success = true;
}
}
This will automatically resolve the issue. BlameableBehavior and TimestampBehavior
// Include these on the start
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;
use Carbon\Carbon;
// Paste this function inside the class.
/**
* #return array
*/
public function behaviors()
{
return [
'blameable' => [
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'created_by',
'updatedByAttribute' => 'updated_by',
],
'timestamp' => [
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => Carbon::now(),
],
];
}
NOTE: If you are not using updated_at or updated_by then remove it
form the above code
change your Behavior in your model to:
public function behaviors()
{
return [
'timestamp' => [
'class' => 'yii\behaviors\TimestampBehavior',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
'value' => new Expression('NOW()'),
],
];
}
if you haven't updated_at also delete it from attributes.
You were getting following warning because you've completely removed the return in the behaviors() method.
"name": "PHP Warning",
"message": "Invalid argument supplied for foreach()",
The behaviors method must return an array. If you don't want to use any behavior your behaviors() method should return empty array like this:
public function behaviors()
{
return [];
}
This is also default implementation of behaviors() method in yii\base\Component so if you don't need to use any behavior you can simply remove the behaviors() method from your model.
Attaching TimestampBehavior to your model when you are not using it means that you add unnecessary overhead.
Example: Rename and prevent time recording or remove properties. Also change the value
Rename or delete properties or change value.
public function behaviors()
{
return [
[
'class' => \yii\behaviors\TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
// 'createdAtAttribute' => 'c_time', //Change the name of the field
'updatedAtAttribute' => false, //false if you do not want to record the creation time.
// 'value' => new Expression('NOW()'), // Change the value
],
];
}
Or
'class' => \yii\behaviors\TimestampBehavior::className(),
'attributes' => [
\yii\db\ActiveRecord::EVENT_BEFORE_INSERT => ['created_at'],
// \yii\db\ActiveRecord::EVENT_BEFORE_UPDATE => [],
],
$createdAtAttribute: The attribute that will receive timestamp value Set this property to false if you do not want to record the creation time.
$attributes: List of attributes that are to be automatically filled with the value specified via $value. The array keys are the ActiveRecord events upon which the attributes are to be updated, and the array values are the corresponding attribute(s) to be updated. You can use a string to represent a single attribute, or an array to represent a list of attributes. For example,
[
ActiveRecord::EVENT_BEFORE_INSERT => ['attribute1', 'attribute2'],
ActiveRecord::EVENT_BEFORE_UPDATE => 'attribute2',
]
I've made a really simple function in Laravel 6 that uses with():
$forms = Form::with('itemsForms')->get();
return response()->json([
'code' => 200,
'data' => $forms
]);
The following are the relationships between Form and ItemsForm:
//Form
protected $fillable = [
'title',
'subtitle',
'text',
'name',
'email',
'phone_number',
'address',
'board',
'date',
'file',
'purchasable',
'payment_for',
'invoice_amount',
];
protected $visible = [
'title',
'subtitle',
'text',
'name',
'email',
'phone_number',
'address',
'board',
'date',
'file',
'purchasable',
'payment_for',
'invoice_amount',
];
public function itemsForms()
{
return $this->hasMany('App\ItemsForm');
}
//ItemsForm
protected $fillable = [
'item_id', 'form_id'
];
public function form()
{
return $this->belongsTo('App\Form', 'form_id');
}
The thing is it doesn't retrieve any data from ItemsForm.
Here's some of what I've tried:
I tried changing parameter in with to other similar names but in each case I got an error of "relationship not found" or something like that. When I use itemsForms I get no error.
I tried debugging it enabling the query log. Here's what I got:
array:2 [
0 => array:3 [
"query" => "select * from `forms`"
"bindings" => []
"time" => 5.77
]
1 => array:3 [
"query" => "select * from `items_forms` where `items_forms`.`form_id` in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17)"
"bindings" => []
"time" => 1.03
]
]
I tried getting the ItemsForm data and it retrieves it with no issue (ItemsForm::all()).
Any idea of what could be causing this?
Edit: the schema for ItemsForm is the following:
Schema::create('items_forms', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('item_id');
$table->unsignedBigInteger('form_id');
$table->foreign('item_id')
->references('id')->on('items')
->onDelete('no action')
->onUpdate('no action');
$table->foreign('form_id')
->references('id')->on('forms')
->onDelete('no action')
->onUpdate('no action');
});
Change the relationship as follows..
In Form class
public function itemsForms()
{
return $this->hasMany('App\ItemsForm','form_id','id');
}
In ItemsForm
public function form()
{
return $this->belongsTo('App\Form', 'id','form_id');
}
You can use the relationship as
$res = Form::find($id);
foreach($res->itemsForms as $item)
{
echo $item->item_id;
}
I finally found out what the issue was.
The issue was I didn't include itemsForms in the visible array (even though it is not part of the database fields).
There was no particular reason to include the visible array in my case so I deleted it but if I had wanted to keep it I should have included itemsForms as an element of the array.
I am facing a problem in laravel pagination. In laravel when I called paginate() method it returns
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"first_page_url": "http://laravel.app?page=1",
"last_page_url": "http://laravel.app?page=4",
"next_page_url": "http://laravel.app?page=2",
"prev_page_url": null,
"path": "http://laravel.app",
"from": 1,
"to": 15,
"data":[
{
// Result Object
},
{
// Result Object
}
]
}
This type of Object. What I want is that I want to set data in one vairable for example $a and except data all other value in $b.
But when I added appends('data') of my paginate variable it did not working correctly. I did not find a solution after googling it. Please help me to solve this.
Here is User model
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Authenticatable {
use Notifiable;
use SoftDeletes;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'status', 'role_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
}
My Controller Code is
public function index() {
$users = User::where('status', 1)->paginate(10);
return response()->json(
[
'error' => 0,
'errorMsg' => '',
'data' => [
'users' => $users->appends('data')->toArray(),
],
]
);
}
I tried this code
return response()->json(
[
'error' => 0,
'errorMsg' => '',
'data' => [
'users' => $users->only($user['data'])->toArray(),
'users_pagination' => $users->except($user['data'])->toArray(),
],
]
);
In this users work correctly but users_pagination not working correctly. In both the users, users_pagination returns same value
Try this
$paginateData = User::where('status', 1)->paginate(10);
$arrPaginateData = $paginateData->toArray();
$users = $arrPaginateData['data'];
unset($arrPaginateData['data']); //remove data from paginate array
$pageInfo = $arrPaginateData;
Return in response
return response()->json(
[
'error' => 0,
'errorMsg' => '',
'data' => [
'users' => $users,
'users_pagination' => $pageInfo
],
]
);
Why not try to iterate the object? the below code will attached user specific data into each users.
public function index() {
$users = User::where('status', 1)->paginate(10);
foreach($users as $users){
$users->data = 'your data here';
}
return response()->json([
'error' => 0,
'errorMsg' => '',
'data' => [
'users' => $users,
],
]
);
}
If you want to use Laravel appends you have to follow as per the document.