relational query in yii - php

I have two models named Statement.php and Images.php
In my statement.php model i have a relation saying
'images'=>array(self::HAS_MANY,'Images','statement_id'),
you know what i mean by this line,
Now , i want to execute this relational query ,
$data = Statement::model()->with('images')->findall($criteria);
this query only returns the columns of Statement table not the Images table why?

how you take pictures? example $data->images->id

If you have made sure that there is data in the Images table then
$data = Statement::model()->with('images')->findall($criteria);
will give you the desired output.
Now if you want to access the Images table data then for that you will have to use
$data->images
You cant access the Images data directly.For that you will have to use the relation name.

Related

Laravel relationship where clause returns all records parent

I have three tables, File, FileFolder and Folder. These tables all have their own Laravel Model, with their respective names.
File
FileFolder
Folder
Now, I need to retrieve all files that are in folder 1. Our project already contains an Eloquent relationship within the File model, which looks like this:
public function folderRelation()
{
return $this->belongsTo(FolderFileRelation::class, 'FileId', 'FileId');
}
Looking at the official Laravel docs and these questions on stackoverflow:
where clause inside a relationships - laravel
Laravel query relationship where clause
Laravel relationship where clause is returning records outside relationship
WHERE clause with relationship to another table in Laravel
It clearly states, that for my use case, I need to use the standard with function, to include my relationship, so I can use a where clause on my FileFolder model.
My code now looks like this:
$files = File::with(['folderRelation' => function($query) {
$query->where('FolderId', 1);
}])->get();
Expected outcome
The where-clause on my FileFolder relationship is used, and only the contents from the File table, where the File is in folder 1 get queried from the database.
Returned in $files
Actual outcome
The where-clause on my FileFolder relationship is not used, and all the contents within the File table get queried from the database.
Returned in $files
Did I implement my query correctly, or is it better to use a raw-query in this use case?
Possible solutions
Raw query
Using a raw-query, which would work exactly as I'd want it too. The biggest downside to this method is not being able to use the collections as needed.
Querying folder, then retrieving files
I could query like this:
$files = FileFolder::where('FolderId', $folder)->get()->files();
But, one of my requirements is querying only "image" files, looping over all the files, and dropping keys that are not images, would create an unnecessary extra loop, which would eat away server resources when deployed to production.
(sidenote, sorry for adding the tables as images. I made them with the MD-editor, but couldn't seem to post them due to stackoverflow incorrectly identifying them as code, treating them as inline-code as stated here does not seem to work either)
See here for more detail on the difference between whereHas and with Laravel: Difference between whereHas and with contains constraint
The right code would be the following
$files = File::with(['folderRelation'])->whereHas('folderRelation', function ($query) {
$query->where('FolderId', 0);
})->get();

How to use query builder to retrieve array values from different tables?

Following is the code snippet that I have used in my controller:
public function index(Request $request)
{
$query = DB::table('project_files')->select('project_id')->get()->toArray();
dd($query);
return view ( 'filesync/listfiles' )->with ( $query);
}
So when I try passing the values into the view, I get an array which consists of the project_id from the project_files table. What I would want to do now is to retrieve the project_names of these project_ids, stored in the projects table.I need to use the project_id for the same , but am unable to understand how to relate these using query builder.Any help would be appreciated, meaning how do I use the array values in the query retrieving project names from projects table.
You can setup relationships which is the ideal way or you can use a leftJoin with your query:
DB::table('project_files')->select('project_files.project_id')->leftJoin('projects', 'project_files.project_id', '=', 'projects.project_id')->get()->toArray();
and replace the column name respectively to the correct values.
Another suggestion I would make is to actually make use of the M in MVC by defining models for your table instead of using the db facade.
Note: Don't forget to include the columns you wish to select within your select function.

is it advisable to use polymorphic relations with joins?

I've created migrations and also their relationships. looks like I'm using polymorphic relations, because in one table, I could have the value of one model or i could have the value of another model. as you might guess, I have something like this
ID Mappable_type Mappable_id value
Mappable_type could be one or many other models. mappable_id will be appropriate id from that model. I needed this because I'm creating dynamic form builder and that's how I designed a database.
Now I need to fetch some records from 5 tables together, so I gotta use joins. the table where I have mappable_type is at the third place from those 5 joins. now What should I do also to only fetch data from these 5 joins that have specific model type that is in that morph table? I'm doing something like that for now:
$final = Dynamic::join('dynamic_properties_values','dynamic_properties_values.dynamic_id','=','dynamic.id')
->join('dynamic_properties_mapping','dynamic_properties_mapping.id','=','dynamic_properties_values.mapping_id')
->where('dynamic_properties_mapping.mappable_type','=','App\Driver')
->get();
As you see, I have written by hand something like
"App\Driver"
. It doesn't matter I have written it by hand or had it saved into a variable and than used it here. WHat really bothers me is that let's say when I was inserting data into these morph tables, Model got saved as "App\Driver". what if I make a mistake and when fetching with joins, I write something like App\Http\Driver? or what If I changed the location of the model itself in my code project?
What's the best practice not to make those kind of errors by the time my project reaches huge amount of users?

Simple ORM in PHP MySQL update joined tables

I'm currently trying to write a simple ORM with PHP and mysql. I want the orm class to be able to work with joined tables.
So here's my problem, the following code shows how I map the data the query yields into an array.
public function execute_query($db_connection)
{
$query = '';
foreach($this->sql_query as $query_part)
$query .= $query_part;
$result = $db_connection->query($query);
while($row = $result->fetch_assoc())
{
array_push($this->m_Data, $row);
}
}
db_connection is a mysqli object.
sql_query contains all the different query parts (e.g. sql_query['join'] etc.).
m_Data is the array that contains the data read from the db.
My specific problem now is when I'm using a join statement in my query this function will just override fields with the same name in my m_Data array. Also if I dont save the name's of the table the specific field data is coming from, I later can't update the tables with the same join statement.
tl,dr. I need to be able to not only save the table data like this: m_Data{ 'field_name' => 'value' } but I also need to save the table name the field is selected from. I could then save the data like this m_Data{ 'table_name.field_name' => 'value' } which enables me later to generate a query to update the joined tables successfully.
I cant seem to find any information on how to get the origin table name for each field I pull out of the result.
If it isnt possible with mysqli I'd much appreciate it if you point me in the right direction.
extra short problem statement:
I need to get a result set and read each row seperatly. For each row I need the following information for every field selected: field_name, table_name, value.
There must be a simple answer to this but I seem to be searching for the wrong keywords to find a solution.
I hope I've written this understandable enough.
Seems to me that you should store table column values in an object, so if you have a related table, the column values would be stored in a separate object - and so would not interfere with the values in your primary table.
In general you might work with the ORM this way:
// Make joined query
$rows = ...
foreach($rows as $row)
{
// $row just refers to the primary table
echo $row->id;
// You get a many:1 related table this way
echo $row->getRelatedRow()->value;
// You get a 1:many rows this way
$rows = $row->getOtherRelatedRows();
}
Depending on how you set up your query options, getting related data may or may not initiate further SELECTs to get the required data.
mysqli_result::fetch_fields has useful things:
http://www.php.net/manual/en/mysqli-result.fetch-fields.php
table
orgtable
field type
etc

How do I get results from a database table based on results from a different table in cakephp?

For example I have the following tables in my database:
People
Groups
And in the People table I have the following columns:
Name
Birthdate
Group
In the Groups table I have the following columns:
Name
Colour
Now I want to fetch results from my database to make a list of all the People.
So I would use this:
$this->set('people', $this->Person->find("all"));
And obviously in my view I would loop through the returned array and display it. Now I also want to find out for each person in the list what Colour and Group name they are (retrieved from the groups table).
How would I go about this in CakePHP.
First make sure your model relationships are defined. Second, you might want to consider using "id" fields for your related tables (I assume you did and maybe just did not include them in your original questions table definitions).
And yes, run debug($this->Person->find("all")) as Elwhis noted to see what your array is dumping out.
And if this is a mission critical application, be sure to use containable instead of recursive to prevent taxing queries to your db.
You have to set the recursive attribute. But I guess it should work with the default value. Put this line in your controller debug($this->Person->find("all")) and check whether the data doesn't already contain you desired group information.
If not, try setting $this->Person->recursive = 1; before calling the find() function
For more information about recursive: http://book.cakephp.org/view/1063/recursive

Categories