zend db table model and query multiple tables - zend-framework

Just like in codeigniter model class, can we have multiple methods calling different tables in zend framework model that extends zend_db_table_abstract ?
protected $_name = table_name
when defining table name like that, Is there a way to query multiple table having no affect of that protected property ? I am mainly concern about this because I want to have model for homepage which will deal with frontend website and fetch data from different table so that i don't have to touch backend db-table models.

You can also access the DB adapter member in the table and query it directly, specifying a table name of your choice.
For instance, for a select, you can do something like the following:
$select = $this->getAdapter()->select();
$select->from('tableName', $fields);
// ...
$results = $this->getAdapter()->fetchAll($select);
Hope that helps,

Try protected $_name = array(1=>'table1', 2=>'table2', /*etc...*/);
And add a foreach() to your code when the query is made, like this:
foreach ($_name as $table)
{
// execute your query
}
It should work, I used this in my CMS for the AdminZone...

Related

Call to undefined method Illuminate\Database\Query\Builder::with() when retrieving orders with providers and services

I am trying to retrieve orders with their service names and provider names all which are in a many to many relationship.
Additionally, I want to use joins to get the client, name.
I have thus used the code bellow
$orders = DB::table('orders')
->join('users', 'orders.user', 'users.id')
->select('users.name As client', 'orders.id', 'orders.amount As amount','orders.description As description', 'orders.status As status')
->with('providers')
->with('services')
->where(['orders.status'=>1])
->get();
In the Order model class, I have implemented the relationships as follows
public function providers()
{
return $this->belongsToMany(ServiceProvider::class)
->as('provider');
}
public function services()
{
return $this->belongsToMany(Service::class)
->as('service');
}
With this I am expecting to retrieve each order with all the services and providers related to it and since I have a foreign key user linking orders to users table, I have used joins to get the name of the user who placed the order as client. Now my problem is that this is not working and is giving the error above. Does this mean that the with() method does not exist in database query builder? if so what method can I use with database query builder to achieve this? Incase there is none, how can I use eloquent ORM to achieve the same purpose?
When you use the DB::table() method, you are not using your Models, so the ->with() method, which is used to include Relationships is not available. To handle this, please use your Models:
$orders = Order::join('users', 'orders.user', 'users.id')
->select('users.name As client', 'orders.id', 'orders.amount As amount','orders.description As description', 'orders.status As status')
->with(['providers', 'services'])
->where('orders.status', 1)
->get();
Additional fixes:
The ->with() method can accept an Array of relationships to include:
->with('providers')->with('services') can be written as ->with(['providers', 'services'])
The where() method can accept an array for multiple where clauses, but is unnecessary for a single where clause:
->where(['orders.status'=>1]) is the same as ->where('orders.status', 1)

How to present two tables which have a relation between them like the case of the "sales" table and "sales_content" using the laravel model

I have two tables in my database, one for "sales" informations and the other for "sale content" (items). What is the best method to present this using the laravel models? For example, is it better to create a model for each table or can we only use one?
A Model for each table - you cannot use one Model for multiple tables.
Laravel tries to infer the table name from the Model name based on lowercase pluralisation - so if your Model is called Sale it will presume that the table is called "sales". If your table is something else, you defined the table in the Model using :
protected $table = "online_sales";
Then you will need to define the relationships between the two models - the documentation is here : https://laravel.com/docs/8.x/eloquent-relationships

Using Entity Framework 6 with Multiple DB Schemas but using One DBContext

I have an application using EF as ORM. The database used to have one schema, dbo and everything was working fine. I recently organized my tables into 4 different schemas. Some tables of one schema have dependencies on tables that reside on a different schema. All seems to be valid on the SQL side.
On the app side all db interactions through EF are not working anymore. The code compiles, the schemas are visible in the solution, the model mappings point to the right schemas, but once I try to insert a row to a table it does not work.
I have seen a few posts about using multiple schemas will require using multiple DBContexts but I would rather use one DBContext. All my schemas have the same owner dbo and I do not see a reason of using multiple DBContexts.
Does anyone know if there is a way to achieve this?
You can map each table to its own schema by fluent mapping only. In your DbContext subtype you should override OnModelCreating (if you haven't done so already) and add statements like this:
modelBuilder.Entity<Department>()
.ToTable("t_Department", "school");
Entities that you don't map like this explicitly will be placed in the default dbo schema, or you can provide your own default by
modelBuilder.HasDefaultSchema("sales");
(summarized from here)
In addition to the responce of Gert Arnold, you can also use Table attribute in your entity:
using System.ComponentModel.DataAnnotations.Schema;
[Table("t_Department", Schema = "school")]
public class Department
{
public int Id { get; set; }
public string Name { get; set; }
}
#GertArnold is spot on with his answer. However for pure syntactic candy you can also do this via a convention to pull the schema from the namespace of your models. We found this useful dealing with multiple schemas
modelBuilder.Types().Configure(e => {
var schema = e.ClrType.Namespace.Split('.').Last().ToLower();
var name = entity.ClrType.Name;
return entity.ToTable(name, schema);
});
the above will take the final component of the namespace and use it as the schema name. This avoids the need for customising the table binding for every entity.
In my case, it's possibly that I use DB First to generate my EDMX file, so it doesn't invoke OnModelCreating method.
I finally remove all store:Schema="YourSchema" and Schema="YourSchema" in EDMX file, and I do it by write a bat file with powershell command as below, and execute the bat in the Projec Pre-Build Event:
powershell -Command "$varStr='store:Schema=""abcd""""'; $filePath='%~dp0SomeFolder\SomeFile.edmx'; (gc $filePath) -replace $varStr, '' | Out-File $filePath"

How to use model with multiple identical tables, for data isolation?

I am writing a simple SaaS application for small construction companies to use and am trying to achieve mid-level data isolation by having each company have their own unique data tables that aren't shared.
This is also nice in case the WHERE {group_id} clause is missing, other group data won't be exposed.
I am able to use the command builder to create these tables dynamically, prefixing them with the group number like grp_37645_projects.
But I am stuck on how to use my model classes as the table names change.
After login, I want to set the table names. These won't change as users aren't allowed to be a part of more than one group.
I have read about changing the tableName, but that is a STATIC function, and I have read a little about creating classes on the fly, but neither option was detailed or complete.
I also know this touches on the single table inheritance, but once again, every example use a little different scenario.
Do you have a recommended solution for setting the tableNames dynamically?
Add some logic for tableName:
namespace app\models;
use yii\db\ActiveRecord;
class Project extends ActiveRecord
{
/**
* #return string the name of the table associated with this ActiveRecord class.
*/
public static function tableName()
{
//some logic for getting current "group_id" for current user
$current_group_id = \Yii::$app->user->identity->group_id;
return 'grp_'.$current_group_id.'_projects';
}
}

How can I use a wrapper object as a JPA entity without having a corresponding table in the database

I am building a system on top of an existing (old and messy) database. For this I'm building a JPA layer above the database, but I do not want to map my domain objects directly to the existing database tables.
I currently have a wrapper object that encapsulates 4 entities (data from 4 tables) in the database. Is there a way I can use this wrapper class as a parameter in a JPQL query?
It would be great if the wrapper class itself acted somewhat like a JPA entity, but without having the corresponding database table. Can this be achieved, and if so, how?
For example, how should I change Wrapper
public class Wrapper {
private FirstJpaEntity first;
private SecondJpaEntity second;
}
so that I can use something like
List<Wrapper> wrappers = ...;
TypedQuery<Wrapper> query = entityManager.createQuery(
"SELECT wrap" // This is probably where the problem lies: JPA needs a Type for `wrap`, but this type needs to be an #Entity which `wrap` is not
+ " WHERE wrap IN :wrappers"
+ " AND wrap.first.property = 1"
+ " AND wrap.second.property = 2"
, Wrapper.class);
query.setParameter("wrappers", wrappers);
I looked into making Wrapper an #Embeddable, hoping JPQL could figure out how to navigate through it, but alas #Embeddable objects cannot be queried directly.
Perhaps you can use Multiple Tables via Secondary Tables Annotation/Mapping in your wrapper class?
This way your wrapper can be composed of the four underlying tables but offer a cleaner interface to the application.