Laravel 4 Query against other tables - laravel

I have 4 tables:
partners
users
phones
addresses
The addresses, phones, and partners table each have a fk to the id of the users table to allow a user->owner object environment.
The phones and addresses tables each have a fk to the id in the partners table.
The partners table has a primaryPhone and a primaryAddress field that stores the id to their primary address and phone number.
I want to be able to query all the partners associated with a user and at the same time draw into the array the information pertaining to their primary phone and primary address to display in a grid.
Is there a way to do this in a single query?
partners controller (PartnersController.php)
public function index()
{
$partners = Partners::where('user_id', Auth::user()->id)->get();
return View::make('partners.showall')
->with('partners', $partners)
->with('title', 'partners')
->with('breadcrumb', 'View Partners');
}
Can I get the information for the $partner->primaryPhone into the partners array so that in the view I am able to do a foreach and display the data?
Partners model (Partners.php)
public function phone()
{
return $this->hasMany('Phone', 'partner_id')->where('user_id', Auth::user()->id);
}
public function primaryPhone($id)
{
return $this->has('Phone', 'id')->where('user_id', Auth::user()->id);
}
TABLE STRUCTURES
CREATE TABLE `partners` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`firstName` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`lastName` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`spouseName` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`primaryPhone` int(11) NOT NULL,
`primaryAddress` int(11) NOT NULL,
`primaryEmail` int(11) NOT NULL,
`greeting` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`birthDate` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`spouseBirthDate` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`anniversary` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`notes` text COLLATE utf8_unicode_ci NOT NULL,
`profession` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`spouseProfession` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`pNewsletter` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`eNewsletter` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`partnerStatus` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`photoUrl` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `partners_id_unique` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `phones` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`partner_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`number` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `phones_id_unique` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `addresses` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`partner_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`city` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`state` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`country` int(11) NOT NULL,
`postalcode` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`address_1` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`address_2` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`description` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `addresses_id_unique` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`firstName` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`lastName` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`phoneNumber` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
UNIQUE KEY `users_id_unique` (`id`),
UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

I believe you may be able to use eager loading to load in the related models that you want to show. Docs here: http://laravel.com/docs/eloquent#eager-loading
I think this should work, although haven't tested it myself.
$partners = Partners::with('primaryPhone')->where('user_id', Auth::user()->id)->get();

<?php
$partners = Partners::with('phones')->with('adresses')->where('user_id', Auth::user()->id)->get();
//Now you can loop through the partners
foreach($user->partners as $partner)
{
echo $partner->primaryAdress();
echo $partner->primaryPhone();
}
?>

Related

Need help in Laravel Eloquent for Multiple Join

I have 3 tables. Events, Events_join , Customers . in event_join I have only customer id those who join the event. currently, I fetching events with an array of events_join using this
my DB structure is:
Table structure for table my_events
CREATE TABLE IF NOT EXISTS `my_events` (
`id` int(10) unsigned NOT NULL,
`userid` int(11) NOT NULL,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`sdes` varchar(256) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`pic` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '1',
`sdate` date NOT NULL DEFAULT '1970-01-01',
`edate` date NOT NULL DEFAULT '1970-01-01',
`country` int(11) NOT NULL,
`city` int(11) NOT NULL,
`location` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`url` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`des` varchar(10000) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`cat` int(10) unsigned NOT NULL DEFAULT '1',
`deleted_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`timezone` varchar(90) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Table structure for table customers
CREATE TABLE IF NOT EXISTS `customers` (
`id` int(10) unsigned NOT NULL,
`title` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`firstname` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`lastname` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`username` varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`phone` varchar(40) COLLATE utf8_unicode_ci NOT NULL,
`country` int(10) unsigned NOT NULL DEFAULT '1',
`city` int(10) DEFAULT NULL,
`company` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`password` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`pic` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`level` int(10) unsigned NOT NULL DEFAULT '1',
`status` tinyint(4) NOT NULL DEFAULT '1',
`deleted_at` timestamp NULL DEFAULT NULL,
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Table structure for table events_join
CREATE TABLE IF NOT EXISTS `events_join` (
`id` int(11) NOT NULL,
`userid` int(11) NOT NULL,
`eventid` int(11) NOT NULL,
`sdate` date NOT NULL,
`edate` date NOT NULL,
`date` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
My Events model have this
public function customers()
{
return $this->belongsToMany(Events::class,EventsJoin::class);
}
My Customer model have this
public function events()
{
return $this->belongsToMany(Customer::class,EventsJoin::class);
}
My EventsJoin have this Pivot
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function event()
{
return $this->belongsTo(Events::class);
}
my eventControler have this
$events=Customer::with(['event']);
but its return empty record. the way its working is customers can create events and other customers will join the event. currently those join the events save with userid in events_join table. I want to join events_join table with the customers table so that I can get additional information of the customer.
While not mentioned in your code, I would have to guess that you have 3 Models, one Events, another one for EventsJoin and one for Customers.
What you seem to have, although you don't say it, is a Many to Many relationship in which a Customer can be in Multiple Events and an Event can be joined by Multiple customers.
In Laravel eloquent terms a Many for Many relationship is described with a belongsToMany.
Take a look at the documentation: https://laravel.com/docs/master/eloquent-relationships#many-to-many
Because it is a Many to Many relationship, the EventsJoin needs to extend Pivot and not Model.
So you would have in your Customer Model something like:
public function events()
{
return $this->belongsToMany(Customer::class,EventsJoin::class);
}
And in your EventsJoin Pivot model
public function customer()
{
return $this->belongsTo(Customer::class);
}
public function event()
{
return $this->belongsTo(Event::class);
}
And in your Events Model
public function customers()
{
return $this->belongsToMany(Event::class,EventsJoin::class);
}
When you wish to get the array of event objects you would do $customer->events;
And when you wish to get the array of customers from the event you would do $event->customers;
Do note that plural and singular cases are important for Laravel Eloquent.

Voyager admin menu isn't shown for user with role "admin" with all permissions

I've created new user by regular "Register" link at app frontend, then issued
php artisan voyager:admin this_user#mail.com
and logged in to Voyager with this user's login and password. What I saw is empty space in the panel on the left instead of admin menu:
I've checked roles and permissions in database. In users table this user has role_id set to 1, which is "admin" in table roles and has all permissions in permission_role. This seems to be OK.
Why this user doesn't see the admin menu?
It turns out that two tables were missing from the database: data_rows and data_types. I've recreated them using this:
CREATE TABLE IF NOT EXISTS `data_types` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`slug` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`display_name_singular` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`display_name_plural` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`icon` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`model_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`policy_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`controller` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`generate_permissions` tinyint(1) NOT NULL DEFAULT '0',
`server_side` tinyint(4) NOT NULL DEFAULT '0',
`details` text COLLATE utf8_unicode_ci,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `data_types_name_unique` (`name`),
UNIQUE KEY `data_types_slug_unique` (`slug`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE IF NOT EXISTS `data_rows` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`data_type_id` int(10) unsigned NOT NULL,
`field` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`type` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`display_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`required` tinyint(1) NOT NULL DEFAULT '0',
`browse` tinyint(1) NOT NULL DEFAULT '1',
`read` tinyint(1) NOT NULL DEFAULT '1',
`edit` tinyint(1) NOT NULL DEFAULT '1',
`add` tinyint(1) NOT NULL DEFAULT '1',
`delete` tinyint(1) NOT NULL DEFAULT '1',
`details` text COLLATE utf8_unicode_ci,
`order` int(11) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `data_rows_data_type_id_foreign` (`data_type_id`),
CONSTRAINT `data_rows_data_type_id_foreign` FOREIGN KEY (`data_type_id`) REFERENCES `data_types` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Then I've seeded them by issuing commands:
php artisan db:seed --class=DataTypesTableSeeder
php artisan db:seed --class=DataRowsTableSeeder
Now everything is working fine!

Incorrect datetime error on unrelated field when creating an index

I've got a database with locations table which contains string fields representing address of given location - first line, postcode, city (the table is using timestamps and softDeletes). I'm now creating a cities table, where give location will be connected to city by a foreign key.
The schema for this migration is represented as such:
Schema::create('cities', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->timestamps();
$table->softDeletes();
});
Schema::table('locations', function ($table) {
$table->integer('city_id')->unsigned()->nullable();
$table->foreign('city_id')->references('id')->on('cities');
});
Unfortunately this gives me following error:
Invalid datetime format: 1292 Incorrect datetime value: '0000-00-00 00:00:00' for column 'deleted_
at' at row 154 (SQL: alter table `locations` add constraint `locations_city_id_foreign` foreign key (`city_id`) ref
erences `cities` (`id`))
Now, there's an easy way to fix this, by running following between create cities table and creation of index:
DB::table('locations')->where('deleted_at', "0000-00-00 00:00:00")->update([
'deleted_at' => Carbon::now()
]);
The question is - why creation of index on unrelated column checks a value on deleted_at?
Per comments here's current output of SHOW CREATE TABLE locations:
CREATE TABLE `locations` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`external_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`is_pickup_choice` tinyint(1) DEFAULT '0',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`address_line_1` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`address_line_2` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`town` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`county` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`postcode` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`country` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`longitude` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`latitude` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`type_of_address` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`is_pickup` tinyint(1) DEFAULT '0',
`is_dropoff` tinyint(1) DEFAULT '0',
`is_live` tinyint(1) DEFAULT '0',
`is_actual_point` tinyint(1) DEFAULT '0',
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
`is_near_public_transport` tinyint(1) DEFAULT '0',
`public_transport_notes` longtext COLLATE utf8_unicode_ci,
`notes` longtext COLLATE utf8_unicode_ci,
`url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`is_fictional` tinyint(1) DEFAULT '0',
`city_id` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `locations_latitude_index` (`latitude`),
KEY `locations_longitude_index` (`longitude`),
KEY `locations_deleted_at_index` (`deleted_at`),
KEY `locations_city_id_foreign` (`city_id`),
CONSTRAINT `locations_city_id_foreign` FOREIGN KEY (`city_id`) REFERENCES `cities` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8440 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

Laravel many migrations issue

10 people start new project with laravel.
After for example 2,3 years there will be many migrations.
In case when new programmer joins the team he will setup development environment with code and database.
The problem is that if there are many migrations it will run too slow if there are thousand of migrations.
How to handle this?
Yes running 100s of migrations each time is going to become a headache. You'll want to create a snapshot of your database tables and make that your first migration.
For example lets say you have a blog with a posts and users table. For each table you're going to need a create table statement. If you're working with MySql to get your create table statement for your users table you would query:
SHOW CREATE TABLE users
Once you have your create table statements you can make a new migration which runs those queries and archive all your old migrations.
class CreateSnapshotTables extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
// Create users table
DB::statement("
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`remember_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
);
");
// Create posts table
DB::statement("
CREATE TABLE `posts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
// ...etc.
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
);
");
}
}

Laravel Models Poperty of non-object

I have a People table
CREATE TABLE `people` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`job_title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`profile_pic` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`departments` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
An a departments table
CREATE TABLE `departments` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`people_id` int(11) NOT NULL,
`department_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=50 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
One person can be in many departments
In the departments table the foreign_key is people_id
In my people model
public function departments()
{
return $this->hasMany('App\Models\Departments', 'id', 'people_id');
}
and finally I try and return some results
return $people::find(1)->departments;
I get the error,
**ErrorException in web.php line 129:
Trying to get property of non-object**
Forgive me if this is a stupid error, I have used laravel for a while but never set up models with relationships before.
Try this Piece of code:-
Get All records
$people = People::with('departments')->get();
$people = json_decode(json_encode($people),true) //Convert in to array
echo "<pre>"; print_r($people); die; //print it
Get 1 record
$people = People::with('departments')->first();
$people = json_decode(json_encode($people),true) //Convert in to array
echo "<pre>"; print_r($people); die; //print it
Hope it helps!
So in the end it was a stupid issue.
$people::find(1)->departments;
Find takes an id but the id of 1 did not exist.

Resources