Mysql View in Laravel 5.2 - mysql

This might be simple for someone. But for me I am totally lost. Can anyone give me a heads up for using Mysql View in Laravel 5. I've been searching for relevant post for a while but not a clue except:
DB::statement("Create View")
DB::statement("Drop View")
But this doesn't ring a bell. Any help, any clue, any guide is appreciated.
Thank in advance
My Scenario
I have an employee table with other tables that holds various attributes of the employee separately such as Appointment, posting,health, family etc etc. Most of these tables has one property Is_current to represent the current record of the employee. So whenever I want to display employee profile with latest record or retrieve some latest record from some of these tables, I don't want to retrieve from each an every table one by one. I just want to compile the latest record in a view and retrieve from it whenever I want.
I hope you understand my requirements and sorry for my bad english

I use views all the time for reporting purposes as I can create a denormalized View and then use the power of Models with Scopes and mutators. I wrote an article on how I manage MySQL Views.
# Create a new migration
php artisan make:migration create_employees_record_view
# Update the migration
<?php
use Illuminate\Database\Migrations\Migration;
class CreateEmployeesRecordView extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
\DB::statement("
CREATE VIEW employees_records
AS
SELECT
employees.emp_no,
employees.first_name,
employees.last_name,
employees.gender,
employees.hire_date,
employees.birth_date,
dept_emp.dept_no,
departments.dept_name,
mananger.emp_no AS manager_emp_no,
mananger.first_name AS manager_first_name,
mananger.last_name AS manager_last_name
FROM
employees
LEFT JOIN dept_emp ON employees.emp_no = dept_emp.emp_no
LEFT JOIN departments ON dept_emp.dept_no = departments.dept_no
LEFT JOIN dept_manager ON departments.dept_no = dept_manager.dept_no
LEFT JOIN employees mananger ON dept_manager.emp_no = mananger.emp_no;
");
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
}
}
# Run the migration
php artisan migrate
Managing it via Console Command
php artisan make:command CreateOrReplaceEmployeeRecordsViewCommand
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class CreateOrReplaceEmployeeRecordsViewCommand extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'view:CreateOrReplaceEmployeeRecordsView';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Create or Replace SQL View.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
\DB::statement("
CREATE OR REPLACE VIEW employees_records
AS
SELECT
employees.emp_no,
employees.first_name,
employees.last_name,
employees.gender,
employees.hire_date,
employees.birth_date,
dept_emp.dept_no,
departments.dept_name,
mananger.emp_no AS manager_emp_no,
mananger.first_name AS manager_first_name,
mananger.last_name AS manager_last_name
FROM
employees
LEFT JOIN dept_emp ON employees.emp_no = dept_emp.emp_no
LEFT JOIN departments ON dept_emp.dept_no = departments.dept_no
LEFT JOIN dept_manager ON departments.dept_no = dept_manager.dept_no
LEFT JOIN employees mananger ON dept_manager.emp_no = mananger.emp_no;
");
}
}
Using Model To View
# Create a new model
php artisan make:model EmployeesRecord
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class EmployeesRecord extends Model
{
}
Test out the newly created Model
# For this we will be using tinker
php artisan tinker
>>> $e = \App\EmployeesRecord::first();
=> App\EmployeesRecord {#2885
emp_no: 10001,
first_name: "Georgi",
last_name: "Facello",
gender: "M",
hire_date: "1986-06-26",
birth_date: "1953-09-02",
dept_no: "d005",
dept_name: "Development",
manager_emp_no: 110511,
manager_first_name: "DeForest",
manager_last_name: "Hagimont",
}
>>> $e = \App\EmployeesRecord::where('emp_no', 10003)->first();
=> App\EmployeesRecord {#2896
emp_no: 10003,
first_name: "Parto",
last_name: "Bamford",
gender: "M",
hire_date: "1986-08-28",
birth_date: "1959-12-03",
dept_no: "d004",
dept_name: "Production",
manager_emp_no: 110303,
manager_first_name: "Krassimir",
manager_last_name: "Wegerle",
}
Ref - http://blog.tekz.io/laravel-eloquent-how-to-effectively-manage-sql-views/

To achieve this there is a good article here
I will show some code from the article .
Alter a base class like following:
public function save(array $options = [])
{
$this->toWriteMode();
try {
$saved = parent::save($options);
} catch (\Exception $e) {
$this->toReadMode();
throw $e;
}
$this->toReadMode();
return $saved;
}
protected $readOnly = [];
protected $readOnlyCache = [];
public function save(array $options = [])
{
$this->toWriteMode();
$this->cacheReadOnly();
try {
$saved = parent::save($options);
} catch (\Exception $e) {
$this->toReadMode();
throw $e;
}
$this->toReadMode();
$this->restoreReadOnly();
return $saved;
}
protected function cacheReadOnly()
{
$this->readOnlyCache = [];
foreach ($this->readOnly as $key) {
$value = $this->getAttributeValue($key);
$this->readOnlyCache[$key] = $value;
$this->__unset($key);
}
}
protected function restoreReadOnly()
{
foreach ($this->readOnlyCache as $key => $value) {
$this->setAttribute($key, $value);
}
}
Create Employee model as follows:
class Employee extends BaseModel
{
protected $table = 'employees';
protected $fillable = ['name'];
protected $guarded = ['id'];
public function people()
{
return $this->hasMany('Person');
}
}
Create EagerEmployee class as follows:
class EagerEmployee extends Employee
{
protected $readFrom = 'employeeView'; //Use your view name
protected $readOnly = ['person_ids'];
public function getPersonIdsAttribute($ids)
{
return $this->intArrayAttribute($ids);
}
}
This class will read its data from the view and we can save and retrieve it as normal. It will fetch read only attributes and they will be handled appropriately when saving.
That new intArrayAttribute() method just converts the comma delimited id string returned from the view into an array of integers.
We can use the Employee internally but if we need those extra read only attributes, say in an api response, we can use the EagerEmployee class.
P.S. The above code is copied from the given article and changed according to your needs.
Update:
Since old link to article is broken I'm adding a link to cached page of the site.
New Link to Article
Old Link to Article

'options' => [
\PDO::ATTR_EMULATE_PREPARES => true
]
Add Code to "config/database.php"
see picture below
Show Example

Related

How to get a widget to run with multiple actions from typoscript?

In creating a new uncached widget for login/logout/registering users in the Frontend, am unable to get it to work. How can I call two different controllers from typoscript (see code below)?
Am using TYPO3 9.5. Knowing how to create one is important because I'll need that info in creating many others for various uses. I have previously created a complex login system without widget/controller/action in TYPO3.
In ext_localconf.php, there is;
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
VendorName.ExtensionName,
PluginName,
[
'Frontend' => 'index',
'Account' => 'index,login,logout,register'
], [
'Account' => 'login,logout,register'
]);
Under folder structure Classes/Controller there is class VendorName\ExtensionName\Controller\AccountController which has;
class AccountController extends AbstractWidgetController {
/**
* #var array
*/
protected $supportedRequestTypes = [
Request::class,
WidgetRequest::class
];
public function initializeAction() {
}
public function indexAction() {
}
public function loginAction() {
return $this->view->assign('raw', 'Hello World');
}
public function logoutAction() {
}
public function registerAction() {
}
/**
* Handles a request. The result output is returned by altering the given response.
*
* #param \TYPO3\CMS\Extbase\Mvc\RequestInterface $request The request object
* #param \TYPO3\CMS\Extbase\Mvc\ResponseInterface $response The response, modified by this handler
*
* #return void
* #api
*/
public function processRequest(RequestInterface $request, ResponseInterface $response) {
#ActionController::processRequest($request, $response);
}
}
And in the ts file there is;
page = PAGE
page {
...
10 = USER
10 {
...
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
vendorName = VendorName
extensionName = ExtensionName
pluginName = PluginName
}
}
...
5 = USER_INT
5 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
vendorName = VendorName
extensionName = ExtensionName
pluginName = PluginName
controller = Account
action = login
}
When running this code, the PAGE ts produces the page using the Frontend controller index action which returns raw html through a fluid template. But when I add the USER_INT part, TYPO3 runs out of memory and displays a blank page.
Widgets are a type of ViewHelper used in Fluid templates. From what you describe, I think you want a plugin. Your Controller class needs to extend TYPO3\CMS\Extbase\Mvc\Controller\ActionController, not TYPO3\CMS\Fluid\ViewHelpers\Widget\Controller\AbstractWidgetController for that.

Laravel API pass to Vuejs query join nested transaction and order Ttbles

I am creating a shopping cart and i have 3 tables here as you can see in the image. first is the products, orders and last the transactions, all products that has been ordered will be place in order table along with transaction id whoever belongs to that transaction, and transaction table would record the total balance and change and i want to fetch it in database using laravel query builder and convert it to json like in the 2nd image below, i hope my explanation is not that confusing. Thanks in advance guys :)
Follow the steps below:
1.Creating models and adding relationship between them.
You can create models for transaction , order & product using phpartisan.
php artisan make:model Transaction
php artisan make:model Order
php artisan make:model Product
configure them according to your mysql tables structure.
Adding relationships.
Transaction Model
public function order(){
return $this->hasOne(Order::class, 'transaction_id', 'id');
}
Order Model
public function transaction(){
return $this->belongsTo(Transaction::class);
}
public function products(){
return $this->hasMany(Product::class, 'id', 'product_id');
}
Product Model
public function order(){
return $this->belongsTo(Order::class);
}
2.Creating a controller to handle the results.
You can create a controller using phpartisan.
php artisan make:controller TransactionController -r
Setting up our controller.
public function TransactionDetails($transactionID){
$transaction = Transaction::where('id',$transactionID)->firstOrFail();
$order = $transaction->order;
$products = $order->products;
$result = array();
$result['transaction'] = $transaction;
$result['transaction']['order'] = $order;
$result['transaction']['order']['products'] = $products;
return response()->json($result);
}
This should work and give you your desired output , if any error occurs let me know.
generating models.
php artisan make:model Transaction
php artisan make:model Order
php artisan make:model Product
TransactionModel
public function orders()
{
return $this->hasMany(Order::class, 'transaction_id', 'id');
}
ProductModel
public function orders()
{
return $this->hasMany(Order:class, 'product_id', 'id');
}
OrderMode
public function product()
{
return $this->belongsTo(Product::class, 'product_id', 'id');
}
public function transaction()
{
return $this->belongsTo(Transaction::class, 'transaction_id', 'id');
}
You can create a ResourceCollection to generate your desired JSON output.
php artisan make:resource TransactionCollection
this will create a ResourceCollecion in app\Http\Resource\TransactionCollection
TransactionCollection
class TransactionCollection extends ResourceCollection
{
/**
* Transform the resource collection into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
$transactions = [];
foreach($this->collection as $transaction) {
$jsonTransaction = [
'id' => $transaction->id,
'date' => $transaction->transaction_date,
'total' => $transaction->transaction_total,
'change' => $transaction->transaction_change,
'orders' => []
];
foreach($transaction->orders as $order) {
$product = $order->product;
array_push($jsonTransaction['orders'], [
'id' => $order->id,
'product_name' => $product->product_name,
'category' => $product->product_category,
'price' => $order->order_price,
'quantity' => $order->order_quantity
]);
}
array_push($transactions, $jsonTransaction);
}
}
}
TransactionController
public function getAllTransactions()
{
// this will return your desired json result as you posted in the question.
return TransactionCollection::make(Transaction::all());
}

Laravel Autocomplete using foreign key to show data from another table

i have created an auto complete search box in controller of 'booking' table successfully , but i want the auto complete search box to show data from another table 'patient' that have a one to many relationship with "booking" table according to a specific condition using 'where' condition ,
This is the Booking Controller that i add autocomplete in it:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Booking;
use App\Patient;
use App\User;
use Session;
use DB;
use Auth;
use Input;
class BookingController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$search = \Request::get('search');
$bookings = Booking::whereHas('patient', function ($query) use ($search) {
$query->where('patient_name', 'like', '%' . $search . '%');
})->where('status','=', null)->whereHas('patient', function ($query){
$query->where('company_id','=' ,Auth::user()->company_id);
})->paginate(10);
return view('booking.index')->withBookings($bookings);
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function autoComplete(Request $request) {
$query = $request->get('term','');
$bookings=Booking::whereHas('patient', function ($query){
$query->where('company_id','=' ,Auth::user()->company_id);
})->$data=array();
foreach ($bookings as $booking) {
$data[]=array('value'=>$booking->patient->patient_name,'id'=>$booking->id);
}
if(count($data))
return $data;
else
return ['value'=>'No Result Found','id'=>''];
}
and this is the Booking Model :
class Booking extends Eloquent
{
public function patient()
{
return $this->belongsTo('App\Patient');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
and this is the patient Model:
class Patient extends Eloquent
{
public function booking()
{
return $this->hasMany('App\Booking');
}
public function user()
{
return $this->belongsTo('App\User');
}
}
and i used this code in view :
{!! Form::text('search_text', null, array('placeholder' => 'Search Text','class' => 'form-control','id'=>'search_text')) !!}
i want to show data from "patient" table and there is a one to many relationship between "booking" and "patient" table and i have successfully made a search box to search in patient table as you can see in index function , but i dont know to show data from "patient" table using where condition to show patient_name that his company_id equal Authenticated user company_id
Sorry for my Bad Language .

Yii2 How to create a globally accessible variable that converts user's id to employee's id

I have two tables that are related directly in a one-to-one relationship. One is the standard Yii2 user table (abbreviated field list here for clarity) and the other is the employee table that contains user_id. How can I create a globally accessible variable (and the actual code to access the employee id) that I can use anywhere in my application that will give me the logged in user's employee id and how would I call that variable? I wish I could say that I've tried a few things, but unfortunately I am relatively new to Yii2 and have no idea where to start with global variables like this. Thanks for any help.
user table:
id
username
password
etc
employee table:
id
user_id (related in a one-to-one relationship to the user table)
The Employee Model:
<?php
namespace frontend\models\base;
use Yii;
/**
* This is the base model class for table "employee".
*
* #property integer $id
* #property integer $user_id
*
* #property \common\models\User $user
*/
class Employee extends \yii\db\ActiveRecord
{
public function rules()
{
return [
[['user_id', 'required'],
[['user_id'], 'integer'],
[['user_id'], 'unique']
];
}
public static function tableName()
{
return 'employee';
}
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'user_id' => Yii::t('app', 'User ID'),
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(\common\models\User::className(), ['id' => 'user_id']);
}
}
A very simple way is the use of $param array
You can initially config the default value in
your_App\config\param.php
and accessing using
\Yii::$app->params['your_param_key']
Looking to your Employee model (for me ) you don't need a global var you could simply use the getUser
$myUser = Employee::user();
but you need the param you can assign using
\Yii::$app->params['my_user'] = Employee::user();
or in user
\Yii::$app->params['my_user'] = Yii::$app->user->id
or for retrive the model related to actual user from table
$myEmpModel = Employee::find()->where['user_id' => Yii::$app->user->id]->one();
I believe proper way is to use relations in your User model. First method is proper relation with activerecord, second one will get id using relation defined above it. so You will add these methods in your User model:
/**
* #return \yii\db\ActiveQuery
*/
public function getEmployee()
{
return $this->hasOne(Employee::className(), ['user_id' => 'id']);
}
public function getEmployeeId()
{
return $this->employee ? $this->employee->id : NULL; // set to NULL or anything you expect to be if record is not found
}
Then you can call it like this from everywhere in your app:
$employee_id = Yii::$app->user->identity->employeeid;
This will only work for User model because it implements Identity, otherwise you would need to instantiate model class first, lets say like this:
$user_id = 5; // 5 is id of user record in DB
$user = User::findOne($user_id);
$employee_id = $user->employeeid;
// or using first of 2 relations ...
$employee_id = $user->employee->id;

When Extending Zend_Db_Table_Abstract to Create a Join it Crashes MySQL

I want to understand why this works perfect with out a problem.
$this->db = Zend_Db_Table_Abstract::getDefaultAdapter();
public function getMessages()
{
$select = $this->db->select();
$select
->from('Mail_Text', '*')
->join(
array('Mail' => 'Mail'),
'Mail.id = Mail_Text.parent_id', '*'
);
return $this->db->fetchAll($select);
}
Now if I do this by extending Zend_Db_Table_Abstract
class Mail_Model_Text extends Zend_Db_Table_Abstract
{
protected $_name = 'Mail_Text';
public function fetchMessges(){
$select = $this->select();
$select->setIntegrityCheck(false)
->from($this->_name, '*')
->join(
array('Mail' => 'Mail'),
'Mail.id = Mail_Text.parent_id', '*'
);
return $this->fetchAll($select);
}
}
This crashes MySql I wanted to keep the code separate but I can join theses tables. All the Single select and updates query's work perfect. I have research all over the net and can't seem to find the solution to this puzzle. Any Help to his would be great Thanks in advance.
You don't need the from() statement or need to alias the table to the same name:
class Mail_Model_Text extends Zend_Db_Table_Abstract
{
protected $_name = 'Mail_Text';
public function fetchMessges()
{
$select = $this->select();
$select->setIntegrityCheck(false)
->join('Mail', 'Mail.id = Mail_Text.parent_id');
return $this->fetchAll($select);
}
}
Also, ensure that you have correctly indexed your tables.