How to use laravel Eloquent to take just one field? - php

I am new in Laravel and I am watching a video tutorial that is teaching Laravel 3, unfortunately Laravel 4 is very different with laravel 3 and I don't know why? and I am afraid that maybe laravel 5 will be so different with laravel 4.
I am going to select all data about one field from my users table:
$user=new user;
$username=$user::find(1)->username;
return $username;
The top code is working true but just return the username of a user that it's id is equal to 1, But I want to do something like below:
$user=new user;
$username=$user::all()->username;
return $username;
This code has error $user::all()->username; and the error is :
Undefined property: Illuminate\Database\Eloquent\Collection::$username

You can use the lists() function, described here
It will return an array with all the values of one property.
(Also you don't need to create an instance to retrieve all users)
$usernames = User::lists('username');
If you'd like to have another column as key of your array (e.g. the id) do this:
$usernames = User::lists('username', 'id');
Don't be worried about Laravel 5. Some things will change but many things will stay the same. Including everything about Eloquent and the DB querying in general (at least as far as I know)

Related

How to get latest record in Laravel 9 [duplicate]

I would like to retrieve the last file inserted into my table. I know that the method first() exists and provides you with the first file in the table but I don't know how to get the last insert.
You'll need to order by the same field you're ordering by now, but descending.
As an example, if you have a time stamp when the upload was done called upload_time, you'd do something like this;
For Pre-Laravel 4
return DB::table('files')->order_by('upload_time', 'desc')->first();
For Laravel 4 and onwards
return DB::table('files')->orderBy('upload_time', 'desc')->first();
For Laravel 5.7 and onwards
return DB::table('files')->latest('upload_time')->first();
This will order the rows in the files table by upload time, descending order, and take the first one. This will be the latest uploaded file.
Use the latest scope provided by Laravel out of the box.
Model::latest()->first();
That way you're not retrieving all the records. A nicer shortcut to orderBy.
You never mentioned whether you are using Eloquent, Laravel's default ORM or not. In case you are, let's say you want to get the latest entry of a User table, by created_at, you probably could do as follow:
User::orderBy('created_at', 'desc')->first();
First it orders users by created_at field, descendingly, and then it takes the first record of the result.
That will return you an instance of the User object, not a collection. Of course, to make use of this alternative, you got to have a User model, extending Eloquent class. This may sound a bit confusing, but it's really easy to get started and ORM can be really helpful.
For more information, check out the official documentation which is pretty rich and well detailed.
To get last record details
Model::all()->last(); or
Model::orderBy('id', 'desc')->first();
To get last record id
Model::all()->last()->id; or
Model::orderBy('id', 'desc')->first()->id;
Many answers and some where I don't quite agree. So I will summarise again with my comments.
In case you have just created a new object.
By default, when you create a new object, Laravel returns the new object.
$lastCreatedModel = $model->create($dataArray);
dd($lastCreatedModel); // will output the new output
echo $lastCreatedModel->key; // will output the value from the last created Object
Then there is the approach to combine the methods all() with (last()and first()) without a condition.
Very bad! Don't do that!
Model::get()->last();` // the most recent entry
Model::all()->last();` // the most recent entry
Model::get()->first();` // the oldest entry
Model::all()->first();` // the oldest entry
Which is basically the wrong approach! You get() all() the records, and in some cases that can be 200,000 or more, and then pick out just one row. Not good! Imagine your site is getting traffic from Facebook and then a query like that. In one month that would probably mean the CO² emissions of a city like Paris in a year. Because the servers have to work unnecessarily hard. So forget this approach and if you find it in your code, replace it/rewrite it. Maybe you don't notice it with 100 data sets but with 1000 and more it can be noticeable.
Very good would be:
Model::orderBy('id', 'desc')->last(); // the most recent record
Model::latest('id')->first(); // the most recent record
Model::latest('id')->limit(1)->get(); // the most recent record
Model::orderBy('id', 'desc')->limit(1)->get(); // the most recent entry
Model::orderBy('id', 'desc')->first(); // the most recent entry
Model::orderBy('id', 'asc')->first(); // the oldest entry
Model::orderBy('id', 'asc')->limit(1)->get(); // the oldest entry
Model::orderBy('id', 'asc')->first(); // the oldest entry
If orderBy is used in this context, the primarykey should always be used as a basis and not create_at.
Laravel collections has method last
Model::all() -> last(); // last element
Model::all() -> last() -> pluck('name'); // extract value from name field.
This is the best way to do it.
You can use the latest scope provided by Laravel with the field you would like to filter, let's say it'll be ordered by ID, then:
Model::latest('id')->first();
So in this way, you can avoid ordering by created_at field by default at Laravel.
Try this :
Model::latest()->get();
Don't use Model::latest()->first(); because if your collection has multiple rows created at the same timestamp (this will happen when you use database transaction DB::beginTransaction(); and DB::commit()) then the first row of the collection will be returned and obviously this will not be the last row.
Suppose row with id 11, 12, 13 are created using transaction then all of them will have the same timestamp so what you will get by Model::latest()->first(); is the row with id: 11.
To get the last record details, use the code below:
Model::where('field', 'value')->get()->last()
Another fancy way to do it in Laravel 6.x (Unsure but must work for 5.x aswell) :
DB::table('your_table')->get()->last();
You can access fields too :
DB::table('your_table')->get()->last()->id;
Honestly this was SO frustrating I almost had to go through the entire collection of answers here to find out that most of them weren't doing what I wanted. In fact I only wanted to display to the browser the following:
The last row ever created on my table
Just 1 resource
I wasn't looking to ordering a set of resources and order that list through in a descending fashion, the below line of code was what worked for me on a Laravel 8 project.
Model::latest()->limit(1)->get();
Use Model::where('user_id', $user_id)->latest()->get()->first();
it will return only one record, if not find, it will return null.
Hope this will help.
Model($where)->get()->last()->id
For laravel 8:
Model::orderBy('id', 'desc')->withTrashed()->take(1)->first()->id
The resulting sql query:
Model::orderBy('id', 'desc')->withTrashed()->take(1)->toSql()
select * from "timetables" order by "id" desc limit 1
If you are looking for the actual row that you just inserted with Laravel 3 and 4 when you perform a save or create action on a new model like:
$user->save();
-or-
$user = User::create(array('email' => 'example#gmail.com'));
then the inserted model instance will be returned and can be used for further action such as redirecting to the profile page of the user just created.
Looking for the last inserted record works on low volume system will work almost all of the time but if you ever have to inserts go in at the same time you can end up querying to find the wrong record. This can really become a problem in a transactional system where multiple tables need updated.
Somehow all the above doesn't seem to work for me in laravel 5.3,
so i solved my own problem using:
Model::where('user_id', '=', $user_id)->orderBy('created_at', 'desc')->get();
hope am able to bail someone out.
be aware that last(), latest() are not deterministic if you are looking for a sequential or event/ordered record. The last/recent records can have the exact same created_at timestamp, and which you get back is not deterministic. So do orderBy(id|foo)->first(). Other ideas/suggestions on how to be deterministic are welcome.
You just need to retrive data and reverse them you will get your desire record let i explain code for laravel 9
return DB::table('files')->orderBy('upload_time', 'desc')->first();
and if you want no. of x last result
return DB::table('files')->orderBy('upload_time', 'desc')->limit(x)->get();
If the table has date field, this(User::orderBy('created_at', 'desc')->first();) is the best solution, I think.
But there is no date field, Model ::orderBy('id', 'desc')->first()->id; is the best solution, I am sure.
you can use this functions using eloquent :
Model::latest()->take(1)->get();
With pdo we can get the last inserted id in the docs
PDO lastInserted
Process
use Illuminate\Support\Facades\DB;
// ...
$pdo = DB::getPdo();
$id = $pdo->lastInsertId();
echo $id;

Symfony / Doctrine - Get a result based on a json column

I'm using Symfony 6.1, doctrine/orm 2.12.3 and PostgreSQL. Trying to write functional tests, I need to login a user with a ROLE_ADMIN (I used the security bundle as well).
From what I have seen on Symfony Docs, since 5.1 you can log in a user with the loginUser() method, but you can't specify roles or anything. Based on that, I tried to retrieve a user with a custom query in my UserRepository.
I tried using DQL but id doesn't work at all with json, it can't compare the json with the query. The following query always returns null.
public function findOneByRoleAdmin()
{
$rsm = $this->createResultSetMappingBuilder('u');
$sql = $this->getEntityManager()->createNativeQuery('SELECT * FROM public."user" AS u WHERE u.roles::text LIKE \'%ROLE_ADMIN%\' ORDER BY u.id LIMIT 1', $rsm);
return $sql->getOneOrNullResult();
}
Using $sql->getResult() instead of $sql->getOneOrNullResult() returns an empty array.
I know I have data in my test database because dumping a simple findOneBy() shows me the last user created. I also know that the query is valid because it works on the PGAdmin query editor.
I can't figure out why I can't retrieve a user with this, and I don't even know if my workaround is a good one.

How to perform a query having pseudo-relations between two distinct database types?

In a nutshell, the title best discribes my question, but here I am showing the core of the problem.
I have two databases in my web application, One is MariaDB, the other is MongoDB, To give some context, the "user" table in MariaDB stores user information with column "id" it's primary key, there is another "badge" table which stores badge information with also column "id" it's primary key, at last there is "user_badge" collection in MongoDB having documents of fields
{_id, user_id, badge_id, date}
which just links the User with his/her Badges. This is what I meant by pseudo-relation, Unfortunately I don't know what is it called in this situation.
An example:
I want to query and get all users that have a badge with ID 1. So my pseudo-query should do something like "Select all fields from user table where badge_id in user_badge collection is 1". I highlighted like here because this is impossible to be done in a query (based on my knowledge) somehow a query ought to be made on the MongoDB database first then a second have to be made in the MariaDB database against the results of the former query.
Edit: My original question was about how to implement this in Yii2 PHP framework, but when I googled for sometime and I found out no information to do such a thing even in pure PHP, So I decide to end my edited question here, asking for a way to query between a table in an sql database and a collection in a no-sql database, Yet below I leave my old question which just asks for how to do this more specifically in the PHP framework. really if I knew how to do this in pure PHP I can just make a function somehow that does that in the framework if there wasn't any.
Obviously there cannot be a direct primarykey-foriegnkey relation between two database types but I overrided this issue by having a ::hasMany ActiveRecord method in my User Model, and that worked perfectly fine; When I have a User model between hands I just call $model->userBadges to get from MongoDB all documents having that User ID, also vice versa. The problem is when I do a Query involving this relation, I get error
Calling unknown method: yii\mongodb\ActiveQuery::getTableNameAndAlias()
Parts of my Application
User getUserBadges method in User model
public function getUserBadges(){
return $this->hasMany(UserBadge::className(), ['user_id' => 'id']);
}
UserBadge model extending yii\mongodb\ActiveRecord
class UserBadge extends ActiveRecord
{
public static function collectionName()
{
return 'user_badge';
}
public function attributes()
{
return ['_id', 'user_id', 'badge_id', 'date'];
}
public function getUser(){
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
public function getBadge(){
return $this->hasOne(Badge::className(), ['id' => 'badge_id']);
}
}
My query
$query = User::find()->joinWith(['userBadges']);
Edit: I figured out that the previous query is not really what I want, I simplified it to be clear but the real query that I want to do and you will get the point of why I am doing all of this is
$query = User::find()->joinWith(['userBadges'])->where(['badge_id' => 1]);
And with that I can get users from the user table who have a certain badge with id for example 1.
And here the code fails and throws the error stated above. After inspecting for sometime I found the API for the joinWith method
This method allows you to reuse existing relation definitions to perform JOIN queries. Based on the definition of the specified relation(s), the method will append one or multiple JOIN statements to the current query.
And here I knew that it's normal for this error to occur, In my query I am joining a document in a collection of the MongoDB database not a record in a table in a SQL database which definitely wouldn't work. I got stuck here and don't know what to exactly do, I am sticking to have user table in a SQL database and having the user_badge collection in a no-SQL database, what shall I do in such scenario? query on the no-SQL first and then query a SQL query against the result of the former query? or there is already a solution to such a problem in the methods of AcitveQuery? Or my Database structure is invalid?
Thanks in advance.
So after some good time I knew how to do it with the help of this question, where a SQL query is made against a PHP array.
So, first MongoDB will be queried and the results will be stored in an array, then A MariaDB SQL query will be made against the array generated from former query, I am pretty sure that this is not the best option; what if the result of the MongoDB query 100,000? well an array will be made with 100,000 entries, the SQL query will be made using also that 100,000 item array. Yet this is the best answer I could get (until now).
How to implement it in Yii2
// This line query from the MongoDB database and format the data returned well
$userBadges = UserBadge::find()->select(['user_id'])->where(['badge_id' => 1])->column();
// This line make the SQL query using the array generated from the former line
$userQuery = User::find()->where(['id' => $userBadges]);
I hope there can be a better answer for this question that someone can know, But I thought of sharing what I have reached so far.

How to seed a database dummy data using tinker with two each loops - Laravel PHP

I try to seed my mysql database with tinker commands and are struggeling combining two each loops...
I have a table movies, users, and ratings. I want to seed the database with 10 movies, 3 users, and for each user a rating for each movie.
I am putting data into the two tables users und movies and saving those to $movies and $users. And try to create 3 ratings with the user_id and the movie_id for each movie with the following lines.
$users = factory('App\User',3)->create();
$movies= factory('App\Movie',10)->create();
$movies->each(function($movie){ $users->each(function($user){ factory('App\Rating',3)->create(['movie_id'=>$movie->id,'user_id'=>$user->id]);}); });
echoing out $movies and $users show me the data are in there.
The last line gives me back an error:
HP Notice: Undefined variable: users on line 2
tried to simplify the syntax for testing:
$movies->each(function ($movie) {$users->each(function($user) {echo $movie;});});
with the same error.
I guess it is that the $users variable isn't defined inside the first function?
Do I have to define $users inside the first function? How do i do that if i dont want to create 3 new users for each movie? Maybe i can use a for loop somehow to iterate through the users and retrieve the users ids that way?
thanks in advance for helping me
Be sure to use ($users) as well. You need declare the variables used out of the function scope when using Closures in PHP!
$movies->each(function($movie) use ($users){
$users->each(function($user) use ($movie){
factory('App\Rating',3)
->create(['movie_id'=>$movie->id,'user_id'=>$user->id]);
});
});

Select the first 10 rows - Laravel Eloquent

So far I have the following model:
class Listing extends Eloquent {
//Class Logic HERE
}
I want a basic function that retrieves the first 10 rows of my table "listings" and passes them on to the view (via a controller?).
I know this a very basic task but I can't find a simple guide that actually explains step-by-step how to display a basic set of results, whilst detailing what is required in the model, controller and view files.
First you can use a Paginator. This is as simple as:
$allUsers = User::paginate(15);
$someUsers = User::where('votes', '>', 100)->paginate(15);
The variables will contain an instance of Paginator class. all of your data will be stored under data key.
Or you can do something like:
Old versions Laravel.
Model::all()->take(10)->get();
Newer version Laravel.
Model::all()->take(10);
For more reading consider these links:
pagination docs
passing data to views
Eloquent basic usage
A cheat sheet
The simplest way in laravel 5 is:
$listings=Listing::take(10)->get();
return view('view.name',compact('listings'));
Another way to do it is using a limit method:
Listing::limit(10)->get();
This can be useful if you're not trying to implement pagination, but for example, return 10 random rows from a table:
Listing::inRandomOrder()->limit(10)->get();
this worked as well IN LARAVEL 8
Model::query()->take(10)->get();
This also worked in Laravel 9
Model::query()->take(10)->get();

Categories