Custom object based on database table - php

Suppose that I have a database query which looks like below -
select name, gender, birthday from person where person_id = 1;
When this query is executed, some records from the database is returned. I want to execute this query inside a function, then make a custom object which will contain the exact attributes as the column names, with the corresponding values. As an example, suppose that the object is X. So it will have three attributes which are X->name, X->gender and X->birthday, with the corresponding values from the records.
As a second example, consider the following query -
select test1, test2, test3 from test where test_id = 1;
I want to execute this query inside the same function and using the same method, then generate a custom-object Y which will contain the attributes Y->test1, Y->test2 and Y->test3.
Is it doable in PHP? If so, then how?
Edit: By custom object, I meant any kind of object. It does not need to be an instance of a specific class or something like that. I just want to return an object from that function so that I can populate the appropriate classes from the returned object's property values.

foreach ($result as $key => $value)
{
$your_object->{$key} = $value;
}

EDIT: this answer assumed Archangel used MySQL, which it turns out is not the case. Sorry for the mistake! I'll leave my answer here in case any MySQL folks come across it, as well as to preserve the comments if necessary.
If you don't care about custom classes and only want your custom attribute names in the row objects, this is all you need:
$row_object = mysql_fetch_object($result);
Otherwise, you'll need to write your own class yourself (I'm not sure whether a constructor is needed or the function populates your object with data automatically):
class X
{
public $name;
public $gender;
public $birthday;
}
Then call the function like this:
$row_object = mysql_fetch_object($result, 'X');
There's no built-in way that I know of to generate classes on-the-fly for you; you'll have to write your own classes.

Related

CONCAT columns with Laravel 5 eloquent

Consider me as laravel beginner
The goal is: I have two colums, now I need the id to be prefixed with the component name of same row in the table.
For Example (Working)... I have Mysql like
SELECT CONCAT(components.name," ", components.id) AS ID
FROM `components`
And output is
ID
|TestComp 40 |
-------------
|component 41 |
-------------
|test 42 |
I need the same in laravel eloquent way, as here Component is Model name. So i tried something like
$comp=Component::select("CONCAT('name','id') AS ID")->get()
but it doesn't work.
I think because the syntax is wrong.
Kindly help me with the correct syntax. Using laravel Models.
Note: I made the above query, referring this as which available on internet.
User::select(DB::raw('CONCAT(last_name, first_name) AS full_name'))
You need to wrap your query in DB::raw:
$comp = Component::select(DB::raw("CONCAT('name','id') AS ID"))->get()
Also, note because you are doing your query like this, your model might behave differently, because this select removes all other fields from the select statement.
So you can't read the other fields from your model without a new query. So ONLY use this for READING data and not MODIFYING data.
Also, to make it in a nice list, I suggest you modify your query to:
$comp = Component::select(DB::raw("CONCAT('name','id') AS display_name"),'id')->get()->pluck('display_name','id');
// dump output to see how it looks.
dd($comp);// array key should be the arrray index, the value the concatted value.
I came to this post for answers myself. The only problem for me is that the answer didn't really work for my situation. I have numerous table relationships setup and I needed one of the child objects to have a concatenated field. The DB::raw solution was too messy for me. I kept searching and found the answer I needed and feel it's an easier solution.
Instead of DB::raw, I would suggest trying an Eloquent Accessor. Accessors allow you to retrieve model attributes AND to create new ones that are not created by the original model.
For instance, let's say I have a basic USER_PROFILE table. It contains id, first_name, last_name. I have the need to CONCAT the two name attributes to return their user's full name. In the USER_PROFILE Model I created php artisan make:model UserProfile, I would place the following:
class UserProfile extends Model
{
/**
* Get the user's full concatenated name.
* -- Must postfix the word 'Attribute' to the function name
*
* #return string
*/
public function getFullnameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
}
From here, when I make any eloquent calls, I now have access to that additional attribute accessor.
| id | first_name | last_name |
-------------------------------
| 1 | John | Doe |
$user = App\UserProfile::first();
$user->first_name; /** John **/
$user->fullname; /** John Doe **/
I will say that I did run into one issue though. That was trying to create a modified attribute with the same name, like in your example (id, ID). I can modify the id value itself, but because I declared the same name, it appears to only allow access to that field value and no other field.
Others have said they can do it, but I was unable to solve this questions EXACT problem.
I working on posgresql and mysql:
DB::raw('CONCAT(member.last_name, \' \', member.first_name) as full_name')
$text = "other";
$limit = 100
public function get_data($text, $limit)
{
$result = $this->select('titulo', 'codigo', DB::Raw("CONCAT(codigo, ' ', titulo_long) AS text_search"))
->where('tipo', '=', 2)
->having('text_search', 'LIKE', "%$text%")
->limit($limit)
->get();
return $result;
}
}
Here is the example of columns concatenation in Laravel.
I need to search the user by name and I have three columns for the user name (name_first, name_middle, name_last), so I have created a scope in Laravel UserModel which takes $query and user name as the second parameter.
public function scopeFindUserByName($query,$name) {
// Concat the name columns and then apply search query on full name
$query->where(DB::raw(
// REPLACE will remove the double white space with single (As defined)
"REPLACE(
/* CONCAT will concat the columns with defined separator */
CONCAT(
/* COALESCE operator will handle NUll values as defined value. */
COALESCE(name_first,''),' ',
COALESCE(name_middle,''),' ',
COALESCE(name_last,'')
),
' ',' ')"
),
'like', '%' . $name . '%');
}
and you can use this scope anywhere you need to search user by his name, like
UserModel::findUserByName("Max Begueny");
OR
$query = UserModel::query();
$query->findUserByName("Max Begueny");
To check the result of this SQL query just go through from this post.
https://stackoverflow.com/a/62296860/11834856
this code should work:
User::select(\DB::raw('CONCAT(last_name, first_name) AS full_name)')
Scrubbing the Data: Before using Laravel and now, when developing in other languages, I would use CONCAT() on a regular basis. The answers here work to a degree but there still isn't an elegant way to use CONCAT() in Laravel/Eloquent/Query Builder
that I have found.
However, I have found that concatenating the cols AFTER returning the results works well for me and is usually very fast - Scrubbing the data - ( unless you have a huge result which should probably be "chunked" anyway for performance purposes ).
foreach($resultsArray AS $row){
$row['fullname'] = trim($row['firstname']).' '.trim($row['lastname']);
}
This is a tradeoff of course but, personally, I find it to be much more manageable and doesn't limit my use of Eloquent as intended as well as the Query Builder. ( the above is pseudo code - not tested so tweak as needed )
There are other workarounds as well that don't mess with Eloquent/Query Builder functionality such as creating a concatenated col in the table, in this case full_name - save the full name when the record is inserted/updated. This is not uncommon.

Drupal / MySQL fetchAllAssoc(); resulting in exception

I have an external database that I am trying to access from within a Drupal page, I have successfully queried the database and output data to the page using fetchAssoc(), however this only returns the first row in the database. I would like to return all rows into an array for processing, so I'm attempting to use fetchAllAssoc(), this however results in an exception. The database has the following SQL fields:
id, model, manufacturer, url, date_modified
My test code is as follows:
<?php
db_set_active('product_db');
$query = db_select('product', 'p')->fields('p');
$sqlresults = $query->execute()->fetchAllAssoc('id');
foreach($sqlresults as $sqlresult)
{
printf($sqlresult);
}
db_set_active();
?>
I'm thinking that it is the key field 'id' that I am specifying with fetchAllAssoc() that is the problem, as fetchAssoc() prints values correctly. All documentation I have found seems to say that you pass a database field as the key but I have also passed a numeric value with no success.
Many thanks in advance for any advice, I'm sure I'm just missing something stupid.
I think it should work in this way, but within the foreach you want to print the $sqlresult variable as a string, but it is an object (it causes the error).
printf function needs a string as the first parameter, see:
http://php.net/manual/en/function.printf.php
Use for instance var_dump instead:
var_dump($sqlresult);

Filtering a query in parse that the key is a pointer

Im a bit new to the php side of parse, mainly objective-c and swift but I need to write some code that I can query a column (not the objectID one) to return the results..
The column I'm trying to query is a pointer to another class.
Here is the very basic code I have which returns all the rows in the class and the pointers data with the include key, but I need to filter or get only the row/s that I'm looking for.
$query = new ParseQuery("ClassB");
$query->includeKey("ClassA");
$results = $query->find();
In the php sdk I see an option to use equalTo which has a key and a value to it so I tried the following code.
so I choose the column that was the pointer , and its objectid to hopefully only return those row/s that has that object id.
$query = new ParseQuery("ClassB");
$query->includeKey("ClassA");
$query->equalTo("ColumnNameX", "yjdyaGRWP7");
$results = $query->find();
Nothing was returned and a php error was spit out
'pointer field ColumnNameX needs a pointer value' in /var/www/parse/src/Parse/ParseClient.php:326
So im not 100% sure why I cant filter by a ColumnNameX using its objectID which is a pointer to ClassA..
Did I miss something in the PHP docs..
I mean ideally in mysql to just get that row I want would be
SELECT * FROM ClassB WHERE ColunNameX = yjdyaGRWP7
That would return me the row of data, I can use a Join of course to get some info from ClassA as well.
Any thoughts on what im missing or do I need to first query the Class A to get a pointer, then in the equalTo do something like ("ColumnNamX" , $pointerfromClassA) ?
any one have anyone point out what im missing or have a code example.. I have seen some that use the objectID but I dont have access to that.
Ok I figured out one way to do this, not sure if this is the right way but it returns now what I want..
$query->equalTo("ColunNameX", array("__type" => "Pointer", "className" => "ColunNameX", "objectId" => "yjdyaGRWP7"));

Is it possible to get the table from a PDOStatement object?

Say I have a PDOStatement object generated via PDO->query($query), is it possible to get the table it was executed on?
Something like this:
<?php
$statement = $pdo->query('SELECT * FROM `foo`;');
echo $statement->xyz;
// foo
I'm fully aware you can use $query->getColumnMeta(0)['table'] to do it, but as mentioned by the docs, it's not very safe. This needs to work across all PDO drivers.
You can retreive the name of the table using the PDOStatement that retrieves an associative array. The value ['name'] is the name of the table.
$select = $conn_pdo->query('SELECT * FROM foo');
$meta = $select->getColumnMeta(0);
echo "Name of table: ".$meta['table'];
You can check the query string:
$statement->queryString
Remember that a SQL query may reference multiple tables, or no tables, so there is no "table it was executed on". You could use regular expressions on the query string to find the first table referenced for standard queries (SELECT, INSERT, UPDATE, DELETE), but that may not be perfect.
Alternatively, use models to access your data, and you'll always know which tables are accessed by the model definition.
Can you not simply store the string used in the query and use simple string manipulations to access the table?

Doctrine $record->get() with a JOIN

I'm using the following piece of code to retrieve the tags of a shop:
$tags = $this->getObject()->get('Tag');
$this->getObject() returns a Shop object, and ->get('Tag') returns an array of Tag objects related to this shop.
Here's how my database is arranged: 1 Shop = 1 or more Tag, and 1 Tag = 1 Tag_Translation.
What i'd like to do is to retrieve, instead of an array of Tag objects, and array of Tag objects with their translations (in other words, a kind of JOIN).
How is that possible, keeping that same syntax? Thank you very much, i'm new to Doctrine and ORMs in general, i would have had no problem doing it with MySQL but here ...
You may solve this issue like this
a) You can call Tag Models function, when you need the translation
$tag->getTagTranslation()
b) Or you can overwrite your Shop's getTag() function and build your own Query with DQL as #greg0ire suggested, to fetch translation and tag at once
public function getTag(){
return Doctrine_Query::create()
->from("Tag t")
->leftJoin("t.TagTranslation tt")
->addWhere("t.shop_id = ?", $this->getId())
}
(Of course you can name a new function e.g. getTagsWithTranslation())
This assumes, you have built a schema.yml with proper relations !

Categories