ホームページ バックエンド開発 PHPチュートリアル 見落とされていた魔法 - PHP 参照の割り当ての遅延 (遅延データの遅延バインディング)

見落とされていた魔法 - PHP 参照の割り当ての遅延 (遅延データの遅延バインディング)

Jun 23, 2016 pm 01:34 PM

大家 题 このテーマを見れば、今日私が話しているのは PHP の変数参照機能であることは誰でもわかりますが、遅延代入とは何でしょうか?これは主に最近いくつかの機能を最適化する際に思いついたアイデアですが、かなり良いと思うので記録する予定です。以下の疑似コードを見てください:

// 这段代码有人会说为啥不用联表,因为有些业务需求不用联表的效率是联表的3到20倍// 我的项目里基本都是此类写法,比之前联表效率提升很多$a = DB::query("select id from a");$aid = "";foreach($a as $v){	$aid .= $v['id'].','; }$aid = substr($aid, 0 , -1);if($aid){	$b = DB::query("select * from b where aid in ({$aid})");		// 此处省略}
ログイン後にコピー


このコードを例として使用します。これに似たコードが多数あるため、誰でも理解しやすいですが、遅延後の割り当てには必ずしも適しているわけではありません。これは、より寛容であり、効率も同様であるためです。ただし、後の遅延割り当てとははっきりと対照的であり、次の実装方法を誰でも理解しやすくなります。

上記の例を読んだ後、必要なデータとして、ある人の最新 10 件の記事のリストを取得し、各記事に対して 5 つのコメントを読み取り、記事の ID と名前を含めることです。イニシエーターとコメンテーターは、クライアントに指定された形式の JSON に戻ります。以下のコードを参照してください。先頭のコメント '] 変数 $commentList が後で $commentList の値に変更され、これに応じて $data[]['comment'] の値も変更されます。これも後の段階での遅延割り当てです。 , しかし、これに基づいて実装原理について学ぶことができます。

ほとんどの人が同様のコードを書いたことがあると思いますが、このコードに問題があると考える人はほとんどいません。この部分のロジックを分析してみましょう。各記事は 5 つのコメント情報を取得する必要があるため、単純な SQL を使用して 1 つにマージすることはできません。要件は 10 件の記事を取得することだけなので、複雑な SQL 処理を記述するのはループ クエリほど効率的ではありません。 (イントラネットのレイテンシが低い場合) 複雑な SQL の処理効率が遅いのはなぜですか? 数千個のデータを考慮している場合は特に注意する必要はありませんが、数千万個のデータを処理している場合は、複雑な SQL は多くの場合、単純な SQL ほど効率的ではないため、ここではループ クエリを使用して最適化を続けることはできません。しかし、ユーザー情報もループでクエリされることがわかり、これは非常に悪いことです。10 件の投稿がすべて 1 人によって開始され、50 件近くのコメントが大量に投稿されることは望ましくありません。アクティブなユーザー データ。ビジネス ロジックでは、重複したユーザー情報をクエリする可能性が非常に高いため、データベースから重複した情報を取得せず、再利用することが最善です。ユーザー情報はどのように再利用できますか?最終データを組み立てる前に記事のコメント情報を取得し、ユーザーIDを収集し、ユーザー情報を取得して最終データを組み立てるというループが可能です。これは比較的単純な解決策であり、今日は、割り当ての遅延に対処する洗練された方法を見てみましょう。

// 这种需求用联表获取用户信息远没有搜集用户id做in查询效率高$data = array();$article = DB::query("select id,uid,title,content from article where uid={$_GET['uid']} order by id desc limit 10");foreach($article as $v){	$uid = $v['uid'];	$comment = DB::query("select id,uid,content from comment where aid={$v['id']} order by id asc limit 5");		foreach($comment as $value){		$uid .= ','.$value['uid'];	}	// 这里第二个参数我们要求DB类返回的数组以uid为索引	$member = DB::query("select uid,username from user where uid in({$uid})", 'uid');	$commentList = array();	$data[] = array(		'id' => $v['id'],		'title' => $v['title'],		'content' => $v['content'],		'uid' => $v['uid'],		'username' => $member[$v['uid']]['username'],		'comment' => &$commentList	);	foreach($comment as $value){		$commentList[] = array(			'id' => $value['id'],			'content' => $value['content'],			'uid' => $value['uid'],			'username' => $member[$value['uid']]['username']		)	}}	echo json_encode($data);exit;
ログイン後にコピー

このコードが以前と違うのは、一番下に余分なコードがあることですが、それが何の役にも立たないようです。まず、ループ内で記事データの前に変数 $member = array() が初期化され、その後、ループ内で $uid の割り当てが欠落し、コメント投稿者の ID がループ内で収集されます。また、ユーザーデータをクエリするための SQL もコードの下部にあるようです。注意深く検索したところ、&$member[$v['uid']]['username'] と &$member[$value['uid']]['username'] にはさらに & 参照記号があることがわかりました。なぜコードを書くという謎がループから抜け落ちているのか。 $commentList が参照されて後で割り当てられ、$data[]['comment'] が変更されたことを思い出してください。原理は同じです。最初にユーザー情報をクエリするのではなく、存在しない変数を参照する場合、PHP は最初に変数を作成します (例: &$member[$v['uid']][)。 ' username'] の場合、PHP は $member が配列であり宣言されていることを検出しますが、$member[$v['uid']]['username'] は存在せず、メモリ内に作成され、値は null です。

ループ後に記事データを印刷すると、ユーザー名情報がすべて null であることがわかります。もちろん、PHP が割り当てを参照するときにユーザー情報は使用されていませんでした。次に、 $uid = array_keys($member) を使用して、すべてのユーザーの ID 情報を取得します。

为什么array_keys能获取用户id,因为php在引用的时候帮我们创建了$member数组呀,注意一下这里的uid是不重复的哟,之后我们去user表用in检索用户信息,一定注意这里不能把返回的数据赋值给$member因为之前的数据都是引用$member里的数据,如果这里覆盖了$member,内存里两个变量的地址就不一样了,相当于重新创建了一个数组,我们这里赋值给$user,下面的循环是干什么的,当然是修改之前被引用数据的赋值了,我们循环$member变量把$user[$uid]['username']赋值给$member[$uid]['username'],从而改变引用变量的值。在我们把数据绑定到引用变量后千万不要忽略用uset把$member删除了,主要是防止之后的代码里出现操作$member变量的代码,不小心就会把之前绑定好的数据覆盖掉。为啥删除$member之后绑定的数据没有丢失,主要是引用的特性,当多个变量引用一个内存地址时,删除其中一个变量不影响其它变量,除非把所有变量都删除,才会真的删除内存里的数据。php手册是这么解释的“当 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了”。unset($user);只是因为$user是一个临时变量,使用完可以直接从内存释放了。

关于这种编程方式我起名为后期数据延迟绑定,之所以标题是延迟变量赋值主要是让大家便于理解。Php中引用的作用非常广泛,本文所举的例子也只局部的一种使用方法,用来解决编程中遇到类似业务需求的一种处理方式,当然后期数据延迟绑定的编程方法也有很广的使用,希望大家不要局限在本文例子的场景上。针对本文例子是我们编程中最常用的一种问题,我编写了一个函数用来处理数据延迟绑定,减少每个地方都要编写数据绑定的逻辑。

/** * 数据延迟绑定通用方法 *  * @access public * @param array $bindingVar		待绑定的变量 * @param array	$data		待绑定的数据 * @param mixed	$default	默认值 * @return void  */function bindingData(&$bindingVar, $data, $default=''){	foreach($bindingVar as $key => $tmp){		foreach($tmp as $k => $v){			$bindingVar[$key][$k] = isset($data[$key][$k]) ? $data[$key][$k] : $default;		}	}		unset($bindingVar);}
ログイン後にコピー


采用这个函数我们能把之前处理数据绑定的代码部分改成下面这样:

$uid = array_keys($member);if($uid){	$user = DB::query("select uid,username from user where uid in({$uid})", 'uid');	bindingData($member, $user);	unset($member,$user);}
ログイン後にコピー


 

 

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Laravelでフラッシュセッションデータを使用します Laravelでフラッシュセッションデータを使用します Mar 12, 2025 pm 05:08 PM

Laravelは、直感的なフラッシュメソッドを使用して、一時的なセッションデータの処理を簡素化します。これは、アプリケーション内に簡単なメッセージ、アラート、または通知を表示するのに最適です。 データは、デフォルトで次の要求のためにのみ持続します。 $リクエスト -

PHPロギング:PHPログ分析のベストプラクティス PHPロギング:PHPログ分析のベストプラクティス Mar 10, 2025 pm 02:32 PM

PHPロギングは、Webアプリケーションの監視とデバッグ、および重要なイベント、エラー、ランタイムの動作をキャプチャするために不可欠です。システムのパフォーマンスに関する貴重な洞察を提供し、問題の特定に役立ち、より速いトラブルシューティングをサポートします

PHPのカール:REST APIでPHPカール拡張機能を使用する方法 PHPのカール:REST APIでPHPカール拡張機能を使用する方法 Mar 14, 2025 am 11:42 AM

PHPクライアントURL(CURL)拡張機能は、開発者にとって強力なツールであり、リモートサーバーやREST APIとのシームレスな対話を可能にします。尊敬されるマルチプロトコルファイル転送ライブラリであるLibcurlを活用することにより、PHP Curlは効率的なexecuを促進します

Laravelテストでの簡略化されたHTTP応答のモッキング Laravelテストでの簡略化されたHTTP応答のモッキング Mar 12, 2025 pm 05:09 PM

Laravelは簡潔なHTTP応答シミュレーション構文を提供し、HTTP相互作用テストを簡素化します。このアプローチは、テストシミュレーションをより直感的にしながら、コード冗長性を大幅に削減します。 基本的な実装は、さまざまな応答タイプのショートカットを提供します。 Illuminate \ support \ facades \ httpを使用します。 http :: fake([[ 'google.com' => 'hello world'、 'github.com' => ['foo' => 'bar']、 'forge.laravel.com' =>

Codecanyonで12の最高のPHPチャットスクリプト Codecanyonで12の最高のPHPチャットスクリプト Mar 13, 2025 pm 12:08 PM

顧客の最も差し迫った問題にリアルタイムでインスタントソリューションを提供したいですか? ライブチャットを使用すると、顧客とのリアルタイムな会話を行い、すぐに問題を解決できます。それはあなたがあなたのカスタムにより速いサービスを提供することを可能にします

PHPにおける後期静的結合の概念を説明します。 PHPにおける後期静的結合の概念を説明します。 Mar 21, 2025 pm 01:33 PM

記事では、PHP 5.3で導入されたPHPの後期静的結合(LSB)について説明し、より柔軟な継承を求める静的メソッドコールのランタイム解像度を可能にします。 LSBの実用的なアプリケーションと潜在的なパフォーマ

フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 フレームワークのカスタマイズ/拡張:カスタム機能を追加する方法。 Mar 28, 2025 pm 05:12 PM

この記事では、フレームワークにカスタム機能を追加し、アーキテクチャの理解、拡張ポイントの識別、統合とデバッグのベストプラクティスに焦点を当てています。

See all articles