Why the search query always use ID? - php

I'm trying to use ->find()
I want to do query lie this
Where IdBiodata = '$IdBiodata'
Then I try this way :
Route::get('biodata/{IdBiodata}', function ($IdBiodata) {
$databiodata = DB::table('Biodata')->find($IdBiodata);
if(count($databiodata)) {
return view('biodata/vew',compact('databiodata'));
}else{
echo "Data not Found";
}
});
when I run it . I face this
SQLSTATE[42S22]: [Microsoft][SQL Server Native Client 10.0][SQL
Server]Invalid column name 'id'. (SQL: select top 1 * from [Biodata]
where [id] = 1)
how can i fix it ? thanks in advance
My Table structure
CREATE TABLE [dbo].[Biodata](
[IdBiodata] [int] IDENTITY(1,1) NOT NULL,
[Nama] [varchar](max) NULL,
[Umur] [int] NULL,
CONSTRAINT [PK_Biodata] PRIMARY KEY CLUSTERED
(
[IdBiodata] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

your search query written using query builder not using Eloquent ORM.find() function Retrieving A Record By Primary Key and Primary Key always take column name as id untill and unless you can not defined externally.
So $databiodata = DB::table('Biodata')->find($IdBiodata); when you write this it's assume Primary key as id.
in Eloquent ORM you can change Primary Key
class Biodata extends Eloquent {
protected $primaryKey = 'IdBiodata';
}
Now, you can write
Biodata::find($IdBiodata);
if you don't wan to use Eloquent ORM so simply use other function rather than find() use where()
$databiodata = DB::table('Biodata')->where('IdBiodata',$IdBiodata)->get();
SO now Replace Your Code using below code
From this
$databiodata = DB::table('Biodata')->find($IdBiodata);
To
$databiodata = DB::table('Biodata')->where('IdBiodata',$IdBiodata)->get();

find() function always use the primary key .. you can use where() instead of find() if you're going to filter it by other field .. here's an example using your query
$databiodata = DB::table('Biodata')->where('IdBiodata',$IdBiodata)->get();

Related

Eloquent add optional condition to hasMany where foreign key is null

How do you add an optional/OR condition to a eloquent relationship?
E.g I want all the users comments OR where the foreign key (user_id) is NULL.
select * from `comments` where (`user_id` is null OR `comments`.`user_id` in (1, 2, 3)) AND `status` = 1
In the User relationship added orWhereNull
public function comments() {
return $this->hasMany(Comments::class)->orWhereNull('user_id');
}
But Laravel it's running:
select * from `comments` where `user_id` is null and `comments`.`user_id` in (1, 2, 3)
Surprised this hasn't been asked before only thing I found similar was this:
https://laracasts.com/discuss/channels/eloquent/eloquent-orwherenull-when-where-has-no-results
I tried this but it needs the model not the query builder.
return $this->where(function ($query){
return $query::hasMany(Comment::class)->orWhereNull('user_id');
});
I'm using eager loading to fetch the comments for a list of users.
$users = User::with('comments')->where('active', 1)->paginate(10);
It doesn't work because the "orWhere" is sent to the underlying query builder immediately but the foreign key constraint is added when the query is run. I couldn't work out a nice way to sort that but this workaround is fine for my use case where I'm only selecting one row at a time with this relation (granted I should probably use replace it with a getter...):
(Excuse any mistakes, changing model names for clarity):
class Customer
{
public function selectedOrCurrentWeek(): HasOne
{
return $this->hasOne(Week::class, 'id', 'selected_week_id')
->withDefault(function (Week $instance, Customer $parent) {
return $instance->newQuery()
->whereRaw('CURRENT_TIMESTAMP between start_date and end_date')
->where('customer_id', $parent->id)
->first();
});
}
Query log when fetching a customer by ID :-
select * from `customers` where
`customers`.`id` = ?
and `customers`.`deleted_at` is null
limit 1;
select * from `weeks` where
CURRENT_TIMESTAMP between start_date and end_date
and `customer_id` = ?
and `weeks`.`deleted_at` is null
limit 1;
but it will run the second query once per row
You can optimize this further to your need, just giving an idea on query
$users = User::with('comments', function($query){
$query->where('user_id', '=', null)->where('status', '1');
})->paginate(10);

Laravel 5 save to database and return id

I'm trying to use the eloquent save whilst returning the id of the tuple using
$var=$data->save();
Then trying to return the primary key.Now my primary key is called company_id but when i run:-
$id=$data->company_id
It throws an error saying
column 'id'doesnt exist in the company table.
why does company_id get renamed to id.
place it in your model
protected $primaryKey = 'company_id';
Use insertGetId method to insert a record and then retrieve the ID
here is the example
$id = DB::table('tableName')->insertGetId(
['name' => $request->input('name'),
'address'=> $request->input('address')]
);
print_r($id);

SQL column not found although it exists

I'm using the Laravel framework to create a prototype and need to output an individual article from a database based on it's ID. Seems straightforward but I keep getting the following error when I query the database:
QueryException in Connection.php line 647:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'articles.id' in 'where clause' (SQL: select * from `articles` where `articles`.`id` = 1 limit 1)
I'm trying to retrieve a specific article based on the database column article_id via the articles table in my Article model. I am using a resource route thus the method name 'show' - so I can access via article/{$article_id} in the URL.
Here is my controller:
public function show($article_id) {
$article = Article::find($article_id);
$article->toArray();
return view('articles.view', array('article' => $article));
}
There is no articles.id. It should be articles_id. Am I missing something obvious here?
Thanks in advance, any pointers much appreciated.
The find command looks for whatever is set as the primary key, which by default is id. You can change the primary key in your model:
class Article {
protected $table = 'articles';
protected $primaryKey = 'articles_id';
}
find() searched by primary key, so change the query to:
$article = Article::where('article_id', $article_id)->first();

Order By before Group By using Eloquent (Laravel)

I have a "messages" table with the following columns
CREATE TABLE `messages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`fromId` int(11) NOT NULL,
`toId` int(11) NOT NULL,
`message` text NOT NULL,
`status` int(11) NOT NULL,
`device` varchar(100) NOT NULL,
`createdAt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=57 DEFAULT CHARSET=latin1;
I'm trying to get all messages where 'toId' = $id and grouping by fromId. The problem is that the "message" shown on the results is the first ones, not the latest ones. I tried ordering by createdAt but it's not working.
How can I order by "createdAt" prior to querying and grouping the results? I want to do this in the laravel way using Eloquent.
My query:
$chats = Message::with('sender','recipient')
->where('toId',$id)
->orderBy('createdAt')
->groupBy('fromId')
->paginate(10)
I just needed to do something similar with a messages model. What worked for me was applying the unique method on the returned eloquent collection.
Model::where('toId', $id)
->orderBy('createdAt', 'desc')
->get()
->unique('fromId');
The query will return all messages ordered by createdAt and the unique method will reduce it down to one message for each fromId. This is obviously not as performant as using the database directly, but in my case I have further restrictions on the query.
Also, there are many more useful methods for working with these collections: https://laravel.com/docs/5.2/collections#available-methods
I found a way to do that! Basically, creating a subquery and running it before, so that results are ordered as expected and grouped after.
Here is the code:
$sub = Message::orderBy('createdAt','DESC');
$chats = DB::table(DB::raw("({$sub->toSql()}) as sub"))
->where('toId',$id)
->groupBy('fromId')
->get();
Try this query :
$chats = Message::with('sender','recipient')
->where('toId',$id)
->whereRaw('id IN (select MAX(id) FROM messages GROUP BY fromId)')
->orderBy('createdAt','desc')
->paginate(10)
It should be something along this:
Message::whereToId($id)->groupBy('fromId')->latest('createdAt')->first();
Update
After seeing the query that you've added, you probably just need to add a direction to the orderBy function, like this:
$chats = Message::with('sender','recipient')
->select(DB::raw('*, max(createdAt) as createdAt'))
->where('toId',$id)
->orderBy('createdAt', 'desc')
->groupBy('fromId')
->paginate(10)
This work for me:
(you can remove the order by createdAt in case createAt increase along with id)
DB::select(DB::raw('select * from (select * from messages group by fromId desc) m order by m.createdAt'));
$data = MCCAddMilkEntry::where('coming_from','=','society')
->whereRaw('id = (select max(`id`) from mcc_add_milk_entry)')->get();
#Sergio your answer is good but what if someone wanted to select a related model along with....?
Answer : I have tested every single function but I didn't fetch the correct data.
unique() gives data with associated array.
groupBy() gives better but picking first message.
Solution for Latest inbox messages. My case:
$data = ChatMessage::where('incoming_msg_id', auth()->user()->id)->orWhere('outgoing_msg_id', auth()->user()->id)->latest('msg_id')->with('messageable')->get();
$inbox = [];
$itemIds = [];
foreach ($data as $key => $value) {
if (!in_array($value['messageable_id'].$value['msg_for'], $itemIds)) {
array_push($inbox,$value);
array_push($itemIds,$value['messageable_id'].$value['msg_for']);
}
}
return $this->sendResponse($inbox,'Inbox');
Your case:
$chats = Message::where('toId',$id)->orWhere('fromId', $id)->latest('id')->with('sender','recipient')->get();
$inbox = [];
$fromIds = [];
foreach ($chats as $key => $value) {
if (!in_array($value['fromId'], $fromIds)) {
array_push($inbox,$value);
array_push($fromIds,$value['fromId']);
}
}
return $this->sendResponse($inbox,'Inbox');

How SHOW TABLE sql with TABLE GATEWAY ZF2

How can I 'SHOW TABLE' with tablegateway in Zend Framework 2 ?
I would to execute "show table" sql with tablegateway, can i do it?
In sql I can query the db with this code
"SHOW CREATE TABLE {table_name}"
to have the creation table code.
E.G.
CREATE TABLE `table_name` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date_insert` datetime NOT NULL,
`date_update` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
I have the table model that is declared in this way
class MyTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll($where = false)
{
$select = $this->tableGateway->getSql()->select();
if ($where)
$select->where($where);
$resultSet = $this->tableGateway->selectWith($select);
return $resultSet;
}
public function getShowCreateTable()
{
?????
}
}
How can I get the show create table?
Zend\Db\Metadata is the component you're looking for. It allows you to extract data about the structure of the database your adapter is connected to.
There is also a TableGateway feature you can enable that will populate the TableGateway instance with metadata information. See the docs for it in this section
This will give you the raw structural information of the table, but won't automatically construct a CREATE TABLE statement for you. Since the SHOW CREATE TABLE query you mentioned is not universally supported you have two options:
If you only need to support MySQL/MariaDB then the quickest route to what you're looking for is the query method of the adapter.
If you want it to be portable then you'll need to use one of the methods I described above and combine it with Zend\Db\Sql\Ddl to construct a cross-platform CREATE TABLE statement.

Categories