I tried to display data in the database, the date format in the database is like 2020-10-11T17: 22: 29.000000Z ", how can i change it just to 2020-10-11, or 11 December 2020 ?
This is my controller
public function get_all_artikel(){
$data = ArtikelKonten::select(
'artikel_kategori.nama as kategori','artikel_konten.*')
->join('artikel_kategori','artikel_kategori.id','artikel_konten.id_kategori')
->get();
if ($data){
return response()->json([
'status' => true,
'artikel' => $data,
],200);}
else{
return response()->json([
'status' => false,
'message' => 'No Artikel were found'
],404);}
}
This is my model
class ArtikelKonten extends Model
{
protected $table = 'artikel_konten';
protected $fillable = ['id_kategori', 'gambar', 'tag_program', 'nm_program', 'judul', 'preview', 'konten'];
const CREATED_AT = 'created';
const UPDATED_AT = 'modified';
}
And this is the result
{
"status": true,
"artikel": [
{
"kategori": "Program",
"id": 4,
"id_kategori": "2",
"tag_program": "2",
"nm_program": "Zakat Mall",
"gambar": "http://127.0.0.1:8000/storage/photos/1/article1.png",
"judul": "Mengenalkan Zakat Kepada Anak",
"preview": null,
"konten": null,
"created": "2020-12-10T07:24:50.000000Z",
"modified": "2020-12-10T08:06:07.000000Z"
},
{
"kategori": "Berita",
"id": 10,
"id_kategori": "1",
"tag_program": "4",
"nm_program": "Jumat Barokah",
"gambar": "http://127.0.0.1:8000/storage/photos/1/article2.png",
"judul": "Suplemen Iman Ditengah Pandemi",
"preview": null,
"konten": null,
"created": "2020-12-11T20:44:25.000000Z",
"modified": "2020-12-11T20:44:25.000000Z"
},
{
"kategori": "Program",
"id": 11,
"id_kategori": "2",
"tag_program": "2",
"nm_program": "Zakat Mall",
"gambar": "http://127.0.0.1:8000/storage/photos/1/article3.png",
"judul": "Menumbuhkan Semangat Berzakat Umat",
"preview": null,
"konten": null,
"created": "2020-12-11T20:46:23.000000Z",
"modified": "2020-12-11T20:46:23.000000Z"
}
]
}
I just wana change the "created": "2020-12-11T20:46:23.000000Z", to "create":"2020-12-11", thanks for your answer guys :)
Laravel 7 uses a new date serialization format when using the toArray or toJson method on Eloquent models.
If you would like to keep using the previous behavior you can override the serializeDate() method on your model :
use DateTimeInterface;
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d');
}
See the official upgrade doc here [7.x]
use date() for clear date and time formate
date('d-m-Y', strtotime($value->created));
Eloquent Model has a property called cast to cast the output of the query to the desired format, in your case just cast your date columns like in doc:
class ArtikelKonten extends Model
{
protected $casts = [
'created' => 'datetime:Y-m-d','modified' => 'datetime:Y-m-d'
];
}
Laravel allows to specify the format in which datetime fields should be converted when serialized to array or json
Define $casts property on the model
protected $casts = [
'created_at' => 'datetime:Y-m-d',
'updated_at' => 'datetime:Y-m-d',
];
Read more : https://laravel.com/docs/8.x/eloquent-mutators#date-casting
you cab use accessor for create_at and put this code in your model:
public function getCreatedAtAttribute($date)
{
return Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $date)->format('Y-m-d');
}
First way
Just add to the model:
protected function asDateTime($value)
{
return parent::asDateTime($value)->format('d/m/y');
}
Second way
You can individually customize the format of Eloquent date and datetime casting:
protected $casts = [
'created_at' => 'date:Y-m-d',
'updated_at' => 'datetime:Y-m-d H:00',];
A few links that helped me to answer
link one
A few links that helped me to answer link two
PHP Laravel Framework
Laravel Framework
:
8.42.1
Date tested
:
22 May 2021
PHP version
:
7.3.8
Database
:
MariaDB 10.5.8
OS
:
MacOS 10.13.6 High Sierra
Question
How to transform or change a table column's value/result on the fly e.g. format the timestamp into a date (y-m-d h:i:s) format?
Answer
Using Laravel Eloquent: Mutators & Casting helps the user to transform data values on the fly by defining them in the Model property.
Introduction
Accessors, mutators, and attribute casting allow you to transform Eloquent attribute values when you retrieve or set them on model instances. For example, you may want to use the Laravel encrypter to encrypt a value while it is stored in the database, and then automatically decrypt the attribute when you access it on an Eloquent model. Or, you may want to convert a JSON string that is stored in your database to an array when it is accessed via your Eloquent model.
Attribute Casting
Attribute casting provides functionality similar to accessors and mutators without requiring you to define any additional methods on your model. Instead, your model's $casts property provides a convenient method of converting attributes to common data types.
My table scema
My table data
My front result (before cast)
My front result (post cast)
My model file
<?php
// app/Models/Post.php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
use HasFactory;
protected $fillable = [
'title', 'description'
];
// I've added this because I want to convert timestamp to 'y-m-d' on the fly
protected $casts = [
'created_at' => 'datetime:Y-m-d',
'updated_at' => 'datetime:Y-m-d'
];
}
My controller (I've created controller inside a sub folder 'API')
<?php
// app/Http/Controllers/API/PostController.php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;
use Validator;
class PostController extends Controller
{
// all posts, I'm calling this be the default
public function index()
{
$posts = Post::all()->toArray();
return array_reverse($posts);
}
}
My routes
<?php
// routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\PostController;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::get('posts', [PostController::class, 'index']);
Route::group(['prefix' => 'post'], function () {
Route::post('add', [PostController::class, 'add']);
Route::get('edit/{id}', [PostController::class, 'edit']);
Route::post('update/{id}', [PostController::class, 'update']);
Route::delete('delete/{id}', [PostController::class, 'delete']);
});
My view (Vue)
<template>
<div>
<h3 class="text-center">All Posts</h3><br/>
<table class="table table-bordered table-responsive">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Description</th>
<th>Created At</th>
<th>Updated At</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts" :key="post.id">
<td>{{ post.id }}</td>
<td>{{ post.title }}</td>
<td style="width: 30%">{{ post.description }}</td>
<td>{{ post.created_at }}</td>
<td>{{ post.updated_at }}</td>
<td>
<div class="btn-group" role="group">
<router-link :to="{name: 'edit', params: { id: post.id }}" class="btn btn-primary">Edit
</router-link>
<button class="btn btn-danger" #click="deletePost(post.id)">Delete</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
posts: []
}
},
created() {
this.axios
.get('/api/posts')
.then(response => {
this.posts = response.data;
});
},
methods: {
deletePost(id) {
this.axios
.delete(`/api/post/delete/${id}`)
.then(response => {
let i = this.posts.map(item => item.id).indexOf(id); // find index of your object
this.posts.splice(i, 1)
});
}
}
}
</script>
Related
In one of my models I need to update another attribute when two other attributes from the same model are updated.
In my case, using an Accessor is not an option, because in some cases I will need to do a database query looking for full_phone_number.
What is the best to achive the desired result?
This is my model:
class Address extends Model {
protected $fillable = [
'country_code',
'phone_number',
'full_phone_number',
];
}
When I create a new Address, I need the full_phone_number column to be automatically populated:
$address = Address::create([
'country_code' => 55,
'phone_number' => 1199999999
]);
The expected result is:
# Address model on DB
{
"country_code": 55,
"phone_number": 1199999999,
"full_phone_number": 551199999999
}
When I update country_code or phone_number from an Address, I need the full_phone_number column to be automatically updated:
$address->update([
'phone_number' => 1188888888
]);
The expected result is:
# Address model on DB
{
"country_code": 55,
"phone_number": 1188888888,
"full_phone_number": 551188888888
}
I got the desired result using events, but I don't know if this is the best way to handle this case. The same could be converted to an observer.
class Address extends Model {
protected $fillable = [
'country_code',
'phone_number',
'full_phone_number',
];
protected static function boot()
{
parent::boot();
static::updating(function ($address) {
$address->full_phone_number = $address->country_code . $address->number;
});
}
}
I have some problems with getting time on my app. I'm using laravel api to send informations to my React app.
I have controller like:
public function index(){
$user = auth()->user();
$servers = Server::where('clientid', $user->id)
->orderBy('id', 'desc')
->take(10)
->get();
if ($user) {
$reposne['result'] = true;
$reposne['servers'] = $servers;
} else {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $reposne;
}
And it's successfuly returns what I need, like:
{
"result": true,
"servers": [
{
"id": 2512,
"clientid": 4,
"boxid": 23,
"ipid": 60,
"vazido": 1584355476,
"created_at": null,
"updated_at": null,
"status": "Active"
}
]
}
But as you see there is column vazido that is actyally giving a timestamp. How can I make this time to actual human format?
You can add a $casts attribute in your Server Model and Laravel will handle the rest for you.
Sever Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Server extends Model
{
protected $casts = [
'vazido' => 'datetime:Y-m-d',
];
}
In your model, You can use Eloquent Mutators to formate the date as following.
public function getVazidoAttribute($value)
{
return $value->format('Y-m-d');
}
By default, timestamps are formatted as 'Y-m-d H:i:s'.
I think your column type is int or string. So you can change the column type to timestamp or datetime.
$table->datetime('vazido')->change();
Or you can use mutator to convert the number to the datetime format, add this method to your Server Model:
public function getVazidoAttribute($value) {
return \Carbon\Carbon::createFromTimestamp($value)->format('Y-m-d H:i:s');
}
I'm trying to remove created_at and updated_at before returning response to api . I want to removie these field from both Place_Type and Places
how can I do that? :
I tried : unset(placetypes) but it didn't work
This is my Code:
public function places()
{
$placeType = PlaceType::with('places')->where('id', 1)->get();
return response()->json(['placeType' => $placeType]);
}
The request result:
"placeType": [
{
"id": 1,
"name": "Moriah O'Conner",
"icon": "https://picsum.photos/200/300",
"status": 1,
"created_at": "2019-12-14 18:23:19",
"updated_at": "2019-12-14 18:23:19",
"places": [
{
"id": 1,
"name": "Linda Leffler",
"description": "Alice's shoulder, and it set to work, and very soon came to ME, and told me he was in the air. She did it so VERY remarkable in that; nor did Alice think it would feel very queer to ME.' 'You!' said.",
"icon": "https://picsum.photos/200/300",
"image_name": "https://picsum.photos/200/300",
"rating": 2,
"longitude": -53.389979,
"latitude": 19.633458,
"availability": 1,
"status": 1,
"place_type_id": 1,
"created_at": "2019-12-14 18:23:19",
"updated_at": "2019-12-14 18:23:19"
},
{
"id": 2,
"name": "Lauren Cartwright",
"description": "I should say \"With what porpoise?\"' 'Don't you mean by that?' said the King. 'I can't remember half of anger, and tried to look at it!' This speech caused a remarkable sensation among the leaves.",
"icon": "https://picsum.photos/200/300",
"image_name": "https://picsum.photos/200/300",
"rating": 1,
"longitude": -38.117034,
"latitude": -32.248637,
"availability": 1,
"status": 1,
"place_type_id": 1,
"created_at": "2019-12-14 18:23:19",
"updated_at": "2019-12-14 18:23:19"
}...,
}
Add the fields to the $hidden array:
// Model
protected $hidden = ['created_at', 'updated_at'];
There are different methods you can use.
Method 1 : Fetch only required fields from the database
You can use select() method for retrieving only required fields from db. Hence you can omit the unnecessary fields.
$placeType = PlaceType::with(['places' => function ($query) {
$query->select('id', 'name', 'description', 'icon',
'image_name', 'rating', 'longitude', 'latitude',
'availability', 'status', 'place_type_id'); //timestamps excluded
}])
->select('id', 'name', 'icon', 'status') //timestamps excluded
->where('id', 1)
->get();
return response()->json(['placeType' => $placeType]);
This code will output only specified fields both in the parent model (placetype) and child model (places).
If you use these customized select query more than once and writing all field names multiple time is difficult, then you could use model scope like the following.
PlaceType Model
// add all columns from your table
protected $columns = ['id', 'name', 'icon', 'status', 'created_at', 'updated_at'];
public function scopeExclude($query,$value=[])
{
return $query->select( array_diff( $this->columns,(array) $value) );
}
Place Model
// add all columns from your table
protected $columns = ['id', 'name', 'description', 'icon', 'image_name',
'rating', 'longitude', 'latitude', 'availability',
'status', 'place_type_id', 'created_at', 'updated_at'
];
public function scopeExclude($query,$value=[])
{
return $query->select( array_diff( $this->columns,(array) $value) );
}
Then you could remove unwanted fields like the following
$placeType = PlaceType::with(['places' => function ($query) {
$query->exclude(['created_at', 'updated_at']); //exclude fields from Place model
}])
->exclude(['created_at', 'updated_at']) //exclude fields from PlaceType model
->where('id', 1)
->get();
Courtesy : This SO answer by #Razor
Method 2 : Hide your column from serialization where you need
You can hide your column from serialization using laravel's makeHidden() method. In this method after fetching rows with all fields, you are making the specified fields as hidden. [Please note that the excluded variables won't appear on json but may visible on dump].
//get rows with all fileds (except hidden)
$placeType = PlaceType::with('places')->where('id', 1)->get();
//making timestamps hidden in child model's rows
$placeType->places->makeHidden(['created_at','updated_at']);
//making timestamps hidden in parent model's rows
$placeType->makeHidden(['created_at','updated_at']);
return response()->json($placeType);
Courtesy : This SO answer by #sajed
Method 3 : Using Hidden property
If the timestamps are unnecessary in most of the time in the app, you could use the model's hidden property.
PlaceType Model & Place Model
protected $hidden = ['created_at', 'updated_at'];
Hope this will be helpful. 🤗
1) You just need to declare public $timestamps = false; in every model you want to hide it.
2) You can also disable timestamps by removing $table->timestamps() from your migration.
3) Declare protected $hidden = ['created_at', 'updated_at']; in your model.
In case you want to remove timestamps from model, as mentioned before, place this in your Model:
public $timestamps = false;
Also create a migration with following code in the up() method and run it:
Schema::table('your_table', function (Blueprint $table) {
$table->dropTimestamps();
});
You can use $table->timestamps() in your down() method to allow rolling back.
or in model
const UPDATED_AT = null;
const CREATED_AT = null;
Assuming that $placeType is array, you can use this recursive function:
function removeTimeStampValues($array)
{
if(array_key_exists('created_at', $array) && array_key_exists('updated_at', $array)) {
unset($array['created_at']);
unset($array['updated_at']);
}
foreach ($array as $key => $value) {
if(is_array($value)) {
$array[$key] = recursiveRemoveTimeStampValue($value);
}
}
return $array;
}
If you don't want these columns, you can do as others said based on the documentation (under "Timestamps" title).
But if you need these column and just don't want them in the json response, you can use resource. See the documentation.
First post! New to php & Laravel, figured I'd learn by creating a test project. I've been following Laracasts for guidance but run into issues.
What I'm looking to achieve:
Utilise Guzzle to call for an API
Store response into mySQL database
Setup a route for this
Setup a schedule so the controller runs once a day on schedule (I can start a new thread if need be)
I've got a controller setup for the Guzzle & storing data. I've got a database created which works as intended. The route I'm unsure about though on what exactly needs to be done so I'm struggling here on how to actually run the controller and store the data in the database.
I'd appreciate if anyone could review my code if I've done anything wrong, and give some guidance on routes in context of this.
Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
class DataController extends Controller
{
public function index()
{
$client = new Client(['base_uri' => 'https://api.ratings.food.gov.uk/ratings']);
$response = $client->request('GET', [
'headers' => [
'x-api-version' => '2',
'Accept' => 'application/json'
]
]);
$mydata = json_decode($response->getBody()->getContents(), true);
$object = new Object();
$object->ratingId = $mydata->ratingId;
$object->ratingName = $mydata->ratingName;
$object->ratingKey = $mydata->ratingKey;
$object->ratingKeyName = $mydata->ratingKeyName;
$object->schemeTypeId = $mydata->schemeTypeId;
$object->save();
Requests::insert($object);
}
}
?>
Migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateRatingsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('ratings', function (Blueprint $table) {
$table->bigIncrements('id');
$table->timestamps();
$table->integer('ratingId');
$table->string('ratingName');
$table->string('ratingKey');
$table->string('ratingKeyName');
$table->integer('schemeTypeId');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('ratings');
}
}
API JSON Response Example
{
"ratings": [
{
"ratingId": 12,
"ratingName": "5",
"ratingKey": "fhrs_5_en-gb",
"ratingKeyName": "5",
"schemeTypeId": 1,
"links": [
{
"rel": "self",
"href": "http://api.ratings.food.gov.uk/ratings/12"
}
]
},
{
"ratingId": 11,
"ratingName": "4",
"ratingKey": "fhrs_4_en-gb",
"ratingKeyName": "4",
"schemeTypeId": 1,
"links": [
{
"rel": "self",
"href": "http://api.ratings.food.gov.uk/ratings/11"
}
]
},
{
"ratingId": 10,
"ratingName": "3",
"ratingKey": "fhrs_3_en-gb",
"ratingKeyName": "3",
"schemeTypeId": 1,
"links": [
{
"rel": "self",
"href": "http://api.ratings.food.gov.uk/ratings/10"
}
]
}
}
You should leverage the power of Eloquent ORM. I've found some issues in your code. You need to remove unnecessary lines that you have written there in order to create an object. Considering that you have created the columns with same names as returned by the API response, and considering that your model name is Rating and it should be, here are my suggestions:
Your controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
use App\Rating;
class DataController extends Controller
{
public function index()
{
$client = new Client(['base_uri' => 'https://api.ratings.food.gov.uk/ratings']);
$response = $client->request('GET', [
'headers' => [
'x-api-version' => '2',
'Accept' => 'application/json'
]
]);
$mydata = json_decode($response->getBody()->getContents(), true);
/* You don't need to create an object as you are already parsing the response as an array, so remove below lines */
// $object = new Object();
// $object->ratingId = $mydata->ratingId;
// $object->ratingName = $mydata->ratingName;
// $object->ratingKey = $mydata->ratingKey;
// $object->ratingKeyName = $mydata->ratingKeyName;
// $object->schemeTypeId = $mydata->schemeTypeId;
// $object->save();
Rating::create($mydata);
}
}
And add make the columns fillable in your Rating model by adding a protected static $fillable property to your Rating model:
protected static $fillable = ['ratingId', 'ratingName', 'ratingKeyName', 'schemeTypeId'];
If above solution isn't the one you liked, then you need to either treat $mydata as an array, i.e. do $mydata['ratingId'] to get ratingId, not $mydata->ratingId or remove true argument from json_decode() to parse the response as an object, not an array.
When I call eloquent:
$user = User::where('idUser', 1)->with(['privilege'])->first()->toArray();
It gives me:
{
"idUser": 1,
"name": "UserName",
"email": "UserName#gmail.com",
"image": "https://image.com",
"createdAt": "2019-05-07 15:43:47",
"privilege": {
"idPrivilege": 1,
"name": "user"
}
}
When I call Eloquent:
$user = User::where('idUser', 1)->with(['privilege:name'])->first()->toArray();
Element privilege in json is set to null, but when I call:
$user = User::where('idUser', 1)->with(['privilege:idPrivilege,name'])->first()->toArray();
It is as same as first call. How can I set element privilege to f.e. user (I just want a simple value instead of the full object of Privilege)?
I can use something like:
$user['privilege'] = $user['privilege']['name'];
But this one does not look so nice!
Using resource:
public function toArray($request)
{
return [
'idUser' => $this->idUser,
'name' => $this->name,
'email' => $this->email,
'privilege' => $this->privilege['name'],
'createdAt' => $this->created_at,
];
}
In controller:
$user = User::where('idUser', 1)->with('privilege')->first();
return UserResource::make($user);
Gives:
{
"data": {
"idUser": 1,
"name": "UserName",
"email": "UserName#gmail.com",
"privilege": "user",
"createdAt": "2019-05-07 15:43:47"
}
}
How can i just return object instead of data{object} ?
Try without the backets:
$user = User::where('idUser', $id)->with('privilege:name')->first()->toArray();
or this:
$user = User
::where('idUser', $id)
->with(['privilege' => function($query) {
return $query->select('name');
}])
->first()
->toArray();
But then, you could customize the response to return to your view using API Resources. With this, you can have many different resources to use on the same elements and format the response to any of your needs.
As stated in HCK's answer, you could use
$user = User
::where('idUser', $id)
->with(['privilege' => function($query) {
return $query->select('name');
}])
->first()
->toArray();
To get what you need. Now, if you are already using API Resources, and want to remove the outter data object, you can add the following in your AppServiceProvider boot method:
use Illuminate\Http\Resources\Json\Resource;
class AppServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
Resource::withoutWrapping(); // With this, your resources won't have the
// outter data wrapping
}
}
Just take a look at the docs!